From cea6de7c84fc85b7153b03f37f5634a3c11d2505 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sun, 2 Oct 2011 19:35:15 -0500 Subject: [PATCH 001/240] move ewl_talk from ewlib to erlware commons This is a heavily used module from erlware lib. It makes sense to make it available in erlware commons. Signed-off-by: Jordan Wilberding --- ebin/erlware_commons.app | 5 +- src/ec_talk.erl | 212 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 src/ec_talk.erl diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index 1b4ca40..792980a 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -1,13 +1,14 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.4.0"}, + {vsn, "0.5.0"}, {modules, [ ec_lists, ec_plists, ec_file, ec_string, - ec_semver + ec_semver, + ec_talk ]}, {registered, []}, {applications, [kernel, stdlib]}]}. diff --git a/src/ec_talk.erl b/src/ec_talk.erl new file mode 100644 index 0000000..0823169 --- /dev/null +++ b/src/ec_talk.erl @@ -0,0 +1,212 @@ +%% -*- mode: Erlang; fill-column: 79; comment-column: 70; -*- +%%%--------------------------------------------------------------------------- +%%% Permission is hereby granted, free of charge, to any person +%%% obtaining a copy of this software and associated documentation +%%% files (the "Software"), to deal in the Software without +%%% restriction, including without limitation the rights to use, copy, +%%% modify, merge, publish, distribute, sublicense, and/or sell copies +%%% of the Software, and to permit persons to whom the Software is +%%% furnished to do so, subject to the following conditions: +%%% +%%% The above copyright notice and this permission notice shall be +%%% included in all copies or substantial portions of the Software. +%%% +%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +%%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +%%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +%%% DEALINGS IN THE SOFTWARE. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @doc +%%% Provides the ability to ask questions of the user and +%%% get a response. +%%% @end +%%% @copyright Erlware 2006-2011 +%%%--------------------------------------------------------------------------- +-module(ec_talk). + +%% API +-export([ask/1, + ask/2, + ask_default/2, + ask_default/3, + ask/3, + say/1, + say/2]). + +-export_type([prompt/0, + type/0, + supported/0]). + +-include_lib("eunit/include/eunit.hrl"). + +%%============================================================================ +%% Types +%%============================================================================ +-type prompt() :: string(). +-type type() :: boolean | number | string. +-type supported() :: string() | boolean() | number(). + +%%============================================================================ +%% API +%%============================================================================ + +%% @doc Outputs the line to the screen +-spec say(string()) -> ok. +say(Say) -> + io:format(lists:flatten([Say, "~n"])). + +-spec say(string(), [term()] | term()) -> ok. +say(Say, Args) when is_list(Args) -> + io:format(lists:flatten([Say, "~n"]), Args); +say(Say, Args) -> + io:format(lists:flatten([Say, "~n"]), [Args]). + +%% @doc Asks the user for a response to the specified prompt. +-spec ask(prompt()) -> string(). +ask(Prompt) -> + ask_convert(Prompt, fun get_string/1, string, none). + +%% @doc Asks the user for a response to the specified prompt. +-spec ask_default(prompt(), string()) -> string(). +ask_default(Prompt, Default) -> + ask_convert(Prompt, fun get_string/1, string, Default). + +%% @doc Asks the user to respond to the prompt. Trys to return the +%% value in the format specified by 'Type'. +-spec ask(prompt(), type()) -> supported(). +ask(Prompt, boolean) -> + ask_convert(Prompt, fun get_boolean/1, boolean, none); +ask(Prompt, number) -> + ask_convert(Prompt, fun get_integer/1, number, none); +ask(Prompt, string) -> + ask_convert(Prompt, fun get_integer/1, string, none). + +%% @doc Asks the user to respond to the prompt. Trys to return the +%% value in the format specified by 'Type'. +-spec ask_default(prompt(), type(), supported()) -> supported(). +ask_default(Prompt, boolean, Default) -> + ask_convert(Prompt, fun get_boolean/1, boolean, Default); +ask_default(Prompt, number, Default) -> + ask_convert(Prompt, fun get_integer/1, number, Default); +ask_default(Prompt, string, Default) -> + ask_convert(Prompt, fun get_string/1, string, Default). + +%% @doc Asks the user to respond to the number prompt with a value +%% between min and max. +-spec ask(prompt(), number(), number()) -> number(). +ask(Prompt, Min, Max) + when is_list(Prompt), is_number(Min), is_number(Max) -> + Res = ask(Prompt, fun get_integer/1, none), + case (Res >= Min andalso Res =< Max) of + true -> + Res; + false -> + say("Your answer must be between ~w and ~w!", [Min, Max]), + ask(Prompt, Min, Max) + end. + +%%============================================================================ +%% Internal functions +%% ============================================================================ +%% @doc Actually does the work of asking, checking result and +%% translating result into the requested format. +-spec ask_convert(prompt(), fun(), type(), supported()) -> supported(). +ask_convert(Prompt, TransFun, Type, Default) -> + NewPrompt = Prompt ++ case Default of + none -> + []; + Default -> + " (" ++ sin_utils:term_to_list(Default) ++ ")" + end ++ "> ", + Data = string:strip(string:strip(io:get_line(NewPrompt)), both, $\n), + Ret = TransFun(Data), + case Ret of + no_data -> + case Default of + none -> + say("I didn't get that. This ~p kind of question.~n", [Type]), + ask_convert(Prompt, TransFun, Type, Default); + Default -> + TransFun(Default) + end; + no_clue -> + say("I didn't get that. This ~p kind of question.~n", [Type]), + ask_convert(Prompt, TransFun, Type, Default); + _ -> + Ret + end. + +%% @doc Trys to translate the result into a boolean +-spec get_boolean(string()) -> boolean(). +get_boolean([]) -> + no_data; +get_boolean([$T | _]) -> + true; +get_boolean([$t | _]) -> + true; +get_boolean("ok") -> + true; +get_boolean("OK") -> + true; +get_boolean([$Y | _]) -> + true; +get_boolean([$y | _]) -> + true; +get_boolean([$f | _]) -> + false; +get_boolean([$F | _]) -> + false; +get_boolean([$n | _]) -> + false; +get_boolean([$N | _]) -> + false; +get_boolean(_) -> + no_clue. + +%% @doc Trys to translate the result into an integer +-spec get_integer(string()) -> integer(). +get_integer([]) -> + no_data; +get_integer(String) -> + case (catch list_to_integer(String)) of + {'Exit', _} -> + no_clue; + Integer -> + Integer + end. + +%% @doc Solely returns a string give the string. This is so the same +%% translate function can be used across the board +-spec get_string(string()) -> string(). +get_string([]) -> + no_data; +get_string(String) -> + case is_list(String) of + true -> + String; + false -> + no_clue + end. + +%%%==================================================================== +%%% tests +%%%==================================================================== +general_test_() -> + [?_test(42 == get_integer("42")), + ?_test(500211 == get_integer("500211")), + ?_test(1234567890 == get_integer("1234567890")), + ?_test(12345678901234567890 == get_integer("12345678901234567890")), + ?_test(true == get_boolean("true")), + ?_test(false == get_boolean("false")), + ?_test(true == get_boolean("Ok")), + ?_test(true == get_boolean("ok")), + ?_test(true == get_boolean("Y")), + ?_test(true == get_boolean("y")), + ?_test(false == get_boolean("False")), + ?_test(false == get_boolean("No")), + ?_test(false == get_boolean("no"))]. From ff3557d883af18d849789159c32b8c446d666d98 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 14 Oct 2011 12:29:28 -0500 Subject: [PATCH 002/240] add suport and documentation for signatures for dictionaries Signed-off-by: Jordan Wilberding --- doc/property_based_testing.md | 363 ++++++++++++++++++++++++++ doc/signatures.md | 462 ++++++++++++++++++++++++++++++++++ ebin/erlware_commons.app | 10 +- src/ec_assoc_list.erl | 103 ++++++++ src/ec_dict.erl | 107 ++++++++ src/ec_dictionary.erl | 158 ++++++++++++ src/ec_gb_trees.erl | 223 ++++++++++++++++ src/ec_orddict.erl | 107 ++++++++ src/ec_rbdict.erl | 319 +++++++++++++++++++++++ test/ec_dictionary_proper.erl | 223 ++++++++++++++++ test/mock.erl | 10 + 11 files changed, 2082 insertions(+), 3 deletions(-) create mode 100644 doc/property_based_testing.md create mode 100644 doc/signatures.md create mode 100644 src/ec_assoc_list.erl create mode 100644 src/ec_dict.erl create mode 100644 src/ec_dictionary.erl create mode 100644 src/ec_gb_trees.erl create mode 100644 src/ec_orddict.erl create mode 100644 src/ec_rbdict.erl create mode 100644 test/ec_dictionary_proper.erl create mode 100644 test/mock.erl diff --git a/doc/property_based_testing.md b/doc/property_based_testing.md new file mode 100644 index 0000000..414c962 --- /dev/null +++ b/doc/property_based_testing.md @@ -0,0 +1,363 @@ +Property based testing for unit testers +======================================= + +Main contributors: Torben Hoffmann, Raghav Karol, Eric Merritt + +The purpose of the short document is to help people who are familiar +with unit testing understand how property based testing (PBT) differs, +but also where the thinking is the same. + +This document focusses on the PBT tool +[`PropEr`](https://github.com/manopapad/proper) for Erlang since that is +what I am familiar with, but the general principles applies to all PBT +tools regardless of which language they are written in. + +The approach taken here is that we hear from people who are used to +working with unit testing regarding how they think when designing +their tests and how a concrete test might look. + +These descriptions are then "converted" into the way it works with +PBT, with a clear focus on what stays the same and what is different. + +## Testing philosophies + +### A quote from Martin Logan: + +> For me unit testing is about contracts. I think about the same things +> I think about when I write statements like {ok, Resp} = +> Mod:Func(Args). Unit testing and writing specs are very close for me. +> Hypothetically speaking lets say a function should return return {ok, +> string()} | {error, term()} for all given input parameters then my +> unit tests should be able to show that for a representative set of +> input parameters that those contracts are honored. The art comes in +> thinking about what that set is. + + +The trap in writing all your own tests can often be that we think +about the set in terms of what we coded for and not what may indeed be +asked of our function. As the code is tried in further exploratory +testing and in production new input parameter sets for which the given +function does not meet the stated contract are discovered and added to +the test case once a fix has been put into place. + +This is a very good description of what the ground rules for unit +testing are: + +* Checking that contracts are obeyed. +* Creating a representative set of input parameters. + +The former is very much part of PBT - each property you write will +check a contract, so that thinking is the same. + +## xUnit vs PBT + +Unit testing has become popular for software testing with the advent +of xUnit tools like jUnit for Java. xUnit like tools typically +provide a testing framework with the following functionality + +* test fixture setup +* test case execution +* test fixture teardown +* test suite management +* test status reporting and management + +While xUnit tools provide a lot of functionality to execute and manage +test cases and suites, reporting results there is no focus on test +case execution step, while this is the main focus area of +property-based testing (PBT). + +Consider the following function specification + + :::erlang + sort(list::integer()) ---> list::integer() | error + +A verbal specification of this function is, + +> For all input lists of integers, the sort function returns a sorted +> list of integers. + +For any other kind of argument the function returns the atom error. + +The specification above may be a requirement of how the function +should behave or even how the function does behave. This distinction +is important; the former is the requirement for the function, the +latter is the actual API. Both should be the same and that is what our +testing should confirm. Test cases for this function might look like + + :::erlang + assertEqual(sort([5,4,3,2,1]), [1,2,3,4,5]) + assertEqual(sort([1,2,3,4,5]), [1,2,3,4,5]) + assertEqual(sort([] ), [] ) + assertEqual(sort([-1,0, 1] ), [-1, 0, 1] ) + +How many tests cases should we write to be convinced that the actual +behaviour of the function is the same as its specification? Clearly, +it is impossible to write tests cases for all possible input values, +here all lists of integers, the art of testing is finding individual +input values that are representative of a large part of the input +space. We hope that the test cases are exhaustive to cover the +specification. xUnit tools offer no support for this and this is where +PBT and PBT Tools like `PropEr` and `QuickCheck` come in. + +PBT introduces testing with a large set of random input values and +verifying that the specification holds for each input value +selected. Functions used to generate input values, generators, are +specified using rules and can be simply composed together to construct +complicated values. So, a property based test for the function above +may look like: + + :::erlang + FOREACH({I, J, InputList}, {nat(), nat(), integer_list()}, + SUCHTHAT(I < J andalso J < length(InputList), + SortedList = sort(InputList) + length(SortedList) == length(InputList) + andalso + lists:get(SortedList, I) =< lists:get(SortedList, J)) + + +The property above works as follows + +* Generate a random list of integers `InputList` and two natural numbers + I, J, such that I < J < size of `InputList` +* Check that size of sorted and input lists is the same. +* Check that element with smaller index I is less than or equal to + element with larger index J in `SortedList`. + +Notice in the property above, we *specify* property. Verification of +the property based on random input values will be done by the property +based tool, therefore we can generated a large number of tests cases +with random input values and have a higher level of confidence that +the function when using unit tests alone. + +But it does not stop at generation of input parameters. If you have +more complex tests where you have to generate a series of events and +keep track of some state then your PBT tool will generate random +sequences of events which corresponds to legal sequences of events and +test that your system behaves correctly for all sequences. + +So when you have written a property with associated generators you +have in fact created something that can create numerous test cases - +you just have to tell your PBT tool how many test cases you want to +check the property on. + +## Shrinking the bar + +At this point you might still have the feeling that introducing the +notion of some sort of generators to your unit testing tool of choice +would bring you on par with PBT tools, but wait there is more to +come. + +When a PBT tool creates a test case that fails there is real chance +that it has created a long test case or some big input parameters - +trying to debug that is very much like receiving a humongous log from +a system in the field and try to figure out what cause the system to +fail. + +Enter shrinking... + +When a test case fails the PBT tool will try to shrink the failing +test case down to the essentials by stripping out input elements or +events that does not cause the failure. In most cases this results in +a very short counterexample that clearly states which events and +inputs are required to break a property. + +As we go through some concrete examples later the effects of shrinking +will be shown. + +Shrinking makes it a lot easier to debug problems and is as key to the +strength of PBT as the generators. + +## Converting a unit test + +We will now take a look at one possible way of translating a unit +test into a PBT setting. + +The example comes from Eric Merritt and is about the `add/2` function in +the `ec_dictionary` instance `ec_gb_trees`. + +The add function has the following spec: + + :::erlang + -spec add(ec_dictionary:key(), ec_dictionary:value(), Object::dictionary()) -> + dictionary(). + +and it is supposed to do the obvious: add the key and value pair to +the dictionary and return a new dictionary. + +Eric states his basic expectations as follows: + +1. I can put arbitrary terms into the dictionary as keys +2. I can put arbitrary terms into the dictionary as values +3. When I put a value in the dictionary by a key, I can retrieve that same value +4. When I put a different value in the dictionary by key it does not change other key value pairs. +5. When I update a value the new value in available by the new key +6. When a value does not exist a not found exception is created + +The first two expectations regarding being able to use arbritrary +terms as keys and values is a job for generators. + +The latter four are prime candidates for properties and we will create +one for each of them. + +### Generators + + :::erlang + key() -> any(). + + value() -> any(). + + +For `PropEr` this approach has the drawback that creation and shrinking +becomes rather time consuming, so it might be better to narrow to +something like this: + + :::erlang + key() -> union([integer(),atom()]). + + value() -> union([integer(),atom(),binary(),boolean(),string()]). + +What is best depends on the situation and intended usage. + +Now, being able to generate keys and values is not enough. You also +have to tell `PropEr` how to create a dictionary and in this case we +will use a symbolic generator (detail to be explained later). + + :::erlang + sym_dict() -> + ?SIZED(N,sym_dict(N)). + + sym_dict(0) -> + {'$call',ec_dictionary,new,[ec_gb_trees]}; + sym_dict(N) -> + ?LAZY( + frequency([ + {1, {'$call',ec_dictionary,remove,[key(),sym_dict(N-1)]}}, + {2, {'$call',ec_dictionary,add,[value(),value(),sym_dict(N-1)]}} + ])). + + +`sym_dict/0` uses the `?SIZED` macro to control the size of the +generated dictionary. `PropEr` will start out with small numbers and +gradually raise it. + +`sym_dict/1` is building a dictionary by randomly adding key/value +pairs and removing keys. Eventually the base case is reached which +will create an empty dictionary. + +The `?LAZY` macro is used to defer the calculation of the +`sym_dict(N-1)` until they are needed and `frequency/1` is used +to ensure that twice as many adds compared to removes are done. This +should give rather more interesting dictionaries in the long run, if +not one can alter the frequencies accondingly. + +But does it really work? + +That is a good question and one that should always be asked when +looking at genetors. Fortunately there is a way to see what a +generator produces provided that the generator functions are exported. + +Hint: in most cases it will not hurt to throw in a +`-compile(export_all).` in the module used to specify the +properties. And here we actually have a sub-hint: specify the +properties in a separate file to avoid peeking inside the +implementation! Base the test on the published API as this is what the +users of the code will be restricted to. + +When the test module has been loaded you can test the generators by +starting up an Erlang shell (this example uses the erlware_commons +code so get yourself a clone to play with): + + :::sh + $ erl -pz ebin -pz test + 1> proper_gen:pick(ec_dictionary_proper:key()). + {ok,4} + 2> proper_gen:pick(ec_dictionary_proper:key()). + {ok,35} + 3> proper_gen:pick(ec_dictionary_proper:key()). + {ok,-5} + 4> proper_gen:pick(ec_dictionary_proper:key()). + {ok,48} + 5> proper_gen:pick(ec_dictionary_proper:key()). + {ok,'\036\207_là´?\nc'} + 6> proper_gen:pick(ec_dictionary_proper:value()). + {ok,2} + 7> proper_gen:pick(ec_dictionary_proper:value()). + {ok,-14} + 8> proper_gen:pick(ec_dictionary_proper:value()). + {ok,-3} + 9> proper_gen:pick(ec_dictionary_proper:value()). + {ok,27} + 10> proper_gen:pick(ec_dictionary_proper:value()). + {ok,-8} + 11> proper_gen:pick(ec_dictionary_proper:value()). + {ok,[472765,17121]} + 12> proper_gen:pick(ec_dictionary_proper:value()). + {ok,true} + 13> proper_gen:pick(ec_dictionary_proper:value()). + {ok,<<>>} + 14> proper_gen:pick(ec_dictionary_proper:value()). + {ok,<<89,69,18,148,32,42,238,101>>} + 15> proper_gen:pick(ec_dictionary_proper:sym_dict()). + {ok,{'$call',ec_dictionary,add, + [[114776,1053475], + 'fª\020\227\215', + {'$call',ec_dictionary,add, + ['',true, + {'$call',ec_dictionary,add, + ['2^Ø¡', + [900408,886056], + {'$call',ec_dictionary,add,[[48618|...],<<...>>|...]}]}]}]}} + 16> proper_gen:pick(ec_dictionary_proper:sym_dict()). + {ok,{'$call',ec_dictionary,add, + [10,'a¯\214\031fõC', + {'$call',ec_dictionary,add, + [false,-1, + {'$call',ec_dictionary,remove, + ['d·ÉV÷[', + {'$call',ec_dictionary,remove,[12,{'$call',...}]}]}]}]}} + +That does not look too bad, so we will continue with that for now. + + +### Properties of `add/2` + +The first expectation Eric had about how the dictionary works was that +if a key had been stored it could be retrieved. + +One way of expressing this could be with this property: + + :::erlang + prop_get_after_add_returns_correct_value() -> + ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, + begin + try ec_dictionary:get(K,ec_dictionary:add(K,V,Dict)) of + V -> + true; + _ -> + false + catch + _:_ -> + false + end + end). + +This property reads that for all dictionaries `get/2` using a key +from a key/value pair just inserted using the `add/3` function +will return that value. If that is not the case the property will +evaluate to false. + +Running the property is done using `proper:quickcheck/1`: + + :::sh + proper:quickcheck(ec_dictionary_proper:prop_get_after_add_returns_correct_value()). + .................................................................................................... + OK: Passed 100 test(s). + true + + +This was as expected, but at this point we will take a little detour +and introduce a mistake in the `ec_gb_trees` implementation and see +how that works. + + + diff --git a/doc/signatures.md b/doc/signatures.md new file mode 100644 index 0000000..cf95960 --- /dev/null +++ b/doc/signatures.md @@ -0,0 +1,462 @@ +Signatures +========== + +It often occurs in coding that we need a library, a set of +functionaly. Often there are several algorithms that could provide +this functionality. However, the code that uses it, either doesn't +care about the individual algorithm or wishes to delegate choosing +that algorithm to some higher level. Lets take the concrete example of +dictionaries. A dictionary provides the ability to access a value via +a key (other things as well but primarily this). There are may ways to +implement a dictionary. Just a few are: + +* [Associative Arrays](http://en.wikipedia.org/wiki/Associative_array) +* [Binary Trees](http://en.wikipedia.org/wiki/Binary_tree) +* [Hash Tables](http://en.wikipedia.org/wiki/Hash_table#Performance_analysis) +* [Skip Lists](http://en.wikipedia.org/wiki/Skip_list) +* Many, many more .... + +Each of these approaches has there own performance characteristics, +memory footprints etc. For example, a table of size n with open +addressing has no collisions and holds up to n elements, with a single +comparison for successful lookup, and a table of size n with chaining +and k keys has the minimum max(0, k-n) collisions and O(1 + k/n) +comparisons for lookup. While for skip lists the performance +characteristics are about as good as that of randomly-built binary +search trees - namely (O log n). So the choice of which to select +depends very much on memory available, insert/read characteristics, +etc. So delegating the choice to a single point in your code is a very +good idea. Unfortunately, in Erlang thats ot so easy to do at the moment. + +Other languages, have built in support for this +functionality. [Java](http://en.wikipedia.org/wiki/Java_(programming_language)) +has +[Interfaces](http://download.oracle.com/javase/tutorial/java/IandI/createinterface.html), +[SML](http://en.wikipedia.org/wiki/Standard_ML) has +[Signatures](http://en.wikipedia.org/wiki/Standard_ML#Module_system). +Erlang, though, doesn't currently support this model, at least not +directly. There are a few ways you can approximate it. One way is to +pass the Module name to the calling functions along with the data that +it is going to be called on. + + :::erlang + add(ModuleToUse, Key, Value, DictData) -> + ModuleToUse:add(Key, Value, DictData). + +This works, and you can vary how you want to pass the data. For +example, you could easily use a tuple to contain the data. That is, +you could pass in `{ModuleToUse, DictData}` and that would make it a +bit cleaner. + :::erlang + add(Key, Value, {ModuleToUse, DictData}) -> + ModuleToUse:add(Key, Value, DictData). + +Either way, there are a few problems with this approach. One of the +biggest is that you lose code locality, by looking at this bit of code +you don't know what `ModuleToUse` is at all. You would need to follow +the call chain up to figure out what it is. Also it may not be obvious +what is actually happening. The fact that `ModuleToUse` is a variable +name obscures the code making it harder to understand. The other big +problem is that the tools provided with Erlang can't help find +mistakes that you might have made. Tools like +[Xref](http://www.erlang.org/doc/man/xref.html) and +[Dialyzer](http://www.erlang.org/doc/man/dialyzer.html) have just as +hard a time figuring out the what `ModuleToUse` is pointing to as you +do. So they can't give you warnings about potential problems. In fact +someone could inadvertantly pass an unexpected function name as +`ModuleToUse` and you would never get any warnings, just an exception +at run time. + +Fortunately, Erlang is a pretty flexable language so we can use a +similar approach with a few adjustments to give us the best of both +worlds. Both the flexibiltiy of ignoreing a specific implementation +and keeping all the nice locality we get by using an explicit module +name. + +So what we actually want to do is something mole like this: + + :::erlang + add(Key, Value, DictData) -> + dictionary:add(Key, Value, DictData). + +Doing this we retain the locality. We can easily look up the +`dictionary` Module. We immediately have a good idea what a +`dictionary` actually is and we know what functions we are +calling. Also, all the tools know what a `dictionary` is as well and +how to check that your code is calling it correctly. For all of these +reasons, this is a much better approach to the problem. This is what +*Signatures* are all about. + +Signatures +---------- + +How do we actually do this in Erlang now that Erlang is missing what Java, SML and friends has built in? + +The first thing we need to do is to define +a [Behaviour](http://metajack.im/2008/10/29/custom-behaviors-in-erlang/) +for our functionality. To continue our example we will define a +Behaviour for dictionaries. That Behaviour looks like this: + + :::erlang + -module(ec_dictionary). + + -export([behaviour_info/1]). + + behaviour_info(callbacks) -> + [{new, 0}, + {has_key, 2}, + {get, 2}, + {add, 3}, + {remove, 2}, + {has_value, 2}, + {size, 1}, + {to_list, 1}, + {from_list, 1}, + {keys, 1}]; + behaviour_info(_) -> + undefined. + + +So we have our Behaviour now. Unfortunately, this doesn't give us much +yet. It will make sure that any dictionaries we write will have all +the functions they need to have, but it wont help use actually use the +dictionaries in an abstract way in our code. To do that we need to add +a bit of functionality. We do that by actually implementing our own +behaviour, starting with `new/1`. + + :::erlang + %% @doc create a new dictionary object from the specified module. The + %% module should implement the dictionary behaviour. + %% + %% @param ModuleName The module name. + -spec new(module()) -> dictionary(_K, _V). + new(ModuleName) when is_atom(ModuleName) -> + #dict_t{callback = ModuleName, data = ModuleName:new()}. + +This code creates a new dictionary for us. Or to be more specific it +actually creates a new dictionary Signature record, that will be used +subsequently in other calls. This might look a bit familiar from our +previous less optimal approach. We have both the module name and the +data. here in the record. We call the module name named in +`ModuleName` to create the initial data. We then construct the record +and return that record to the caller and we have a new +dictionary. What about the other functions, the ones that don't create +a dictionary but make use of it. Let's take a look at the +implementations of two kinds of functions, one that updates the +dictionary and another that just retrieves data. + +The first we will look at is the one that updates the dictionary by +adding a value. + + :::erlang + %% @doc add a new value to the existing dictionary. Return a new + %% dictionary containing the value. + %% + %% @param Dict the dictionary object to add too + %% @param Key the key to add + %% @param Value the value to add + -spec add(key(K), value(V), dictionary(K, V)) -> dictionary(K, V). + add(Key, Value, #dict_t{callback = Mod, data = Data} = Dict) -> + Dict#dict_t{data = Mod:add(Key, Value, Data)}. + +There are two key things here. + +1. The dictionary is deconstructed so we can get access to the data +and the callback module. +1. We modify the dictionary record we the new data and return that +modified record. + +This is the same approach that you will use for any Signature that +updates data. As a side note, notice that we are calling the concrete +implementation to do the work itself. + +Now lets do a data retrieval function. In this case, the `get` function +of the dictionary Signature. + + :::erlang + %% @doc given a key return that key from the dictionary. If the key is + %% not found throw a 'not_found' exception. + %% + %% @param Dict The dictionary object to return the value from + %% @param Key The key requested + %% @throws not_found when the key does not exist + -spec get(key(K), dictionary(K, V)) -> value(V). + get(Key, #dict_t{callback = Mod, data = Data}) -> + Mod:get(Key, Data). + +In this case, you can see a very similar approach to deconstructing +the dict record. We still need to pull out the callback module and the +data itself and call the concrete implementation of the algorithm. In +this case, we return the data returned from the call, not the record +itself. + +That is really all you need to define a Signature. There is a complete +implementation in +[erlware_commons/ec_dictionary](https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_dictionary.erl). + +Using Signatures +---------------- + +Its a good idea to work through an example so we have a bit better +idea of how to use these Signatures. If you are like me, you probably +have some questions about what kind of performance burden this places +on the code. At the very least we have an additional function call +along with the record deconstruction. This must add some overhead. So +lets write a little timing test, so we can get a good idea of how much +this is all costing us. + +In general, there are two kinds of concrete implementations for +Signatures. The first is a native implementations, the second is a +wrapper. + +### Native Signature Implementations + +A Native Signature Implementation is just that, a module that +implements the Behaviour defined by a Signature directly. For most +user defined Signatures this is going to be the norm. In our current +example, the +[erlware_commons/ec_rbdict](https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_rbdict.erl) +module is the best example of a Native Signature Implementation. It +implements the ec_dictionary module directly. + +### Signature Wrappers + +A Signature Wrapper is a module that wraps another module. Its +purpose is to help a preexisting module implement the Behaviour +defined by a Signature. A good example if this in our current example +is the +[erlware_commons/ec_dict](https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_dict.erl) +module. It implements the ec_dictionary Behaviour, but all the +functionality is provided by the +[stdlib/dict](http://www.erlang.org/doc/man/dict.html) module +itself. Lets take a look at one example to see how this is done. + +We will take a look at one of the functions we have already seen. The +`get` function an ec_dictionary `get` doesn't have quite the same +semantics as any of the functions in the dict module. So a bit of +translation needs to be done. We do that in the ec_dict module `get` function. + + :::erlang + -spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> + ec_dictionary:value(V). + get(Key, Data) -> + case dict:find(Key, Data) of + {ok, Value} -> + Value; + error -> + throw(not_found) + end. + +So the ec_dict module's purpose for existence is to help the +preexisting dict module implement the Behaviour defined by the +Signature. + + +Why do we bring this up here? Because we are going to be looking at +timings, and Signature Wrappers add an extra level of indirection to +the mix and that adds a bit of additional overhead. + +### Creating the Timing Module + +We are going to creating timings for both Native Signature +Implementations and Signature Wrappers. + +Lets get started by looking at some helper functions. We want +dictionaries to have a bit of data in them. So to that end we are will +create a couple of functions that create dictionaries for each type we +want to test. The first we want to time is the Signature Wrapper, so +`dict` vs `ec_dict` called as a Signature. + + :::erlang + create_dict() -> + lists:foldl(fun(El, Dict) -> + dict:store(El, El, Dict) + end, dict:new(), + lists:seq(1,100)). + +The only thing we do here is create a sequence of numbers 1 to 100, +and then add each of those to the dict as an entry. We aren't too +worried about replicating real data in the dictionary. We care about +timing the function call overhead of Signatures, not the performance +of the dictionaries themselves. + +We need to create a similar function for our Signature based +dictionary `ec_dict`. + + :::erlang + create_dictionary(Type) -> + lists:foldl(fun(El, Dict) -> + ec_dictionary:add(El, El, Dict) + end, + ec_dictionary:new(Type), + lists:seq(1,100)). + +Here we actually create everything using the Signature. So we don't +need one function for each type. We can have one function that can +create anything that implements the Signature. That is the magic of +Signatures. Otherwise, this does the exact same thing as the dict +`create_dict/1`. + +We are going to use two function calls in our timing. One that updates +data and one that returns data, just to get good coverage. For our +dictionaries that we are going to use the `size` function as well as +the `add` function. + + :::erlang + time_direct_vs_signature_dict() -> + io:format("Timing dict~n"), + Dict = create_dict(), + test_avg(fun() -> + dict:size(dict:store(some_key, some_value, Dict)) + end, + 1000000), + io:format("Timing ec_dict implementation of ec_dictionary~n"), + time_dict_type(ec_dict). + +The `test_avg` function runs the provided function the number of times +specified in the second argument and collects timing information. We +are going to run these one million times to get a good average (its +fast so it doesn't take long). You can see that in the anonymous +function that we directly call `dict:size/1` and `dict:store/3` to perform +the test. However, because we are in the wonderful world of Signatures +we don't have to hard code the calls for the Signature +implementations. Lets take a look at the `time_dict_type` function. + + + :::erlang + time_dict_type(Type) -> + io:format("Testing ~p~n", [Type]), + Dict = create_dictionary(Type), + test_avg(fun() -> + ec_dictionary:size(ec_dictionary:add(some_key, some_value, Dict)) + end, + 1000000). + +As you can see we take the type as an argument (we need it for `dict` +creation) and call our create function. Then we run the same timings +that we did for ec dict. In this case though, the type of dictionary +is never specified, we only ever call ec_dictionary, so this test will +work for anything that implements that Signature. + +#### `dict` vs `ec_dict` Results + +So we have our tests, what was the result. Well on my laptop this is +what it looked like. + + :::sh + Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false] + + Eshell V5.8.2 (abort with ^G) + + 1> ec_timing:time_direct_vs_signature_dict(). + Timing dict + Range: 2 - 5621 mics + Median: 3 mics + Average: 3 mics + Timing ec_dict implementation of ec_dictionary + Testing ec_dict + Range: 3 - 6097 mics + Median: 3 mics + Average: 4 mics + 2> + +So for the direct dict call, we average about 3 mics per call, while +for the Signature Wrapper we average around 4. Thats a 25% cost for +Signature Wrappers in this example, for a very small number of +calls. Depending on what you are doing that is going to be greater or +lesser. In any case, we can see that there is some cost associated +with the Signature Wrapper Implementations. + +What about native Signatures though? Lets take a look at +`ec_rbdict`. The `ec_rbdict` also implements the `ec_dictionary` +Signature, but it is not a Signature Wrapper. It is a native +implementation of the Signature. To use `ec_rbdict` directly we have +to create a creation helper just like we did for dict. + + :::erlang + create_rbdict() -> + lists:foldl(fun(El, Dict) -> + ec_rbdict:add(El, El, Dict) + end, ec_rbdict:new(), + lists:seq(1,100)). + +This is exactly the same as `create_dict` with the exception that dict +is replaced by `ec_rbdict`. + +The timing function itself looks very similar as well. Again notice +that we have to hard code the concrete name for the concrete +implementation, but we don't for the ec_dictionary test. + + :::erlang + time_direct_vs_signature_rbdict() -> + io:format("Timing rbdict~n"), + Dict = create_rbdict(), + test_avg(fun() -> + ec_rbdict:size(ec_rbdict:add(some_key, some_value, Dict)) + end, + 1000000), + io:format("Timing ec_dict implementation of ec_dictionary~n"), + time_dict_type(ec_rbdict). + +And there we have our test. What do the results look like? + +#### `ec_rbdict` vs `ec_rbdict` as an `ec_dictionary` Results + +The main thing we are timing here is the additional cost of the +dictionary Signature itself. Keep that in mind as we look at the +results. + + :::sh + Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false] + + Eshell V5.8.2 (abort with ^G) + + 1> ec_timing:time_direct_vs_signature_rbdict(). + Timing rbdict + Range: 6 - 15070 mics + Median: 7 mics + Average: 7 mics + Timing ec_dict implementation of ec_dictionary + Testing ec_rbdict + Range: 6 - 6013 mics + Median: 7 mics + Average: 7 mics + 2> + +So no difference it time. Well the reality is that there is a +difference in timing, there must be, but we don't have enough +resolution in the timing system to be able to figure out what that +difference is. Essentially that means its really, really small - or small +enough not to worry about at the very least. + +Conclusion +---------- + +Signatures are a viable, useful approach to the problem of interfaces +in Erlang. The have little or no over head depending on the type of +implementation, and greatly increase the flexibility of the a library +while retaining testability and locality. + +### Terminology + +Behaviour +: A normal Erlang Behaviour that defines a contract + +Signature +: A combination of an Behaviour and functionality to make the + functions callable in a concrete way + +Native Signature Implementation +: A module that implements a signature directly + +Signature Wrapper +: A module that does translation between a preexisting module and a + Signature, allowing the preexisting module to be used as a Signature + Implementation. + +### Code Referenced + +* [ec_dictionary Implementation] (https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_dictionary.erl) +* [ec_dict Signature Wrapper] (https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_dict.erl) +* [ec_rbdict Native Signature Implementation] (https://github.com/ericbmerritt/erlware_commons/blob/types/src/ec_rbdict.erl) +* [ec_timing Signature Use Example and Timing Collector] (https://github.com/ericbmerritt/erlware_commons/blob/types/examples/ec_timing.erl) diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index 792980a..0fc142e 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -1,14 +1,18 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.5.0"}, + {vsn, "0.6.0"}, {modules, [ ec_lists, ec_plists, ec_file, ec_string, ec_semver, - ec_talk - ]}, + ec_dictionary, + ec_assoc_list, + ec_dict, + ec_gb_trees, + ec_rbdict, + ec_orddict]}, {registered, []}, {applications, [kernel, stdlib]}]}. diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl new file mode 100644 index 0000000..1fdb2c4 --- /dev/null +++ b/src/ec_assoc_list.erl @@ -0,0 +1,103 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% provides an implementation of ec_dictionary using an association +%%% list as a basy +%%% @end +%%% @see ec_dictionary +%%%------------------------------------------------------------------- +-module(ec_assoc_list). + +-behaviour(ec_dictionary). + +%% API +-export([new/0, + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). + +-export_type([dictionary/2]). + +%%%=================================================================== +%%% Types +%%%=================================================================== +-opaque dictionary(K, V) :: {ec_assoc_list, + [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec new() -> dictionary(_K, _V). +new() -> + {ec_assoc_list, []}. + +-spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). +has_key(Key, {ec_assoc_list, Data}) -> + lists:keymember(Key, 1, Data). + +-spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, {ec_assoc_list, Data}) -> + case lists:keyfind(Key, 1, Data) of + {Key, Value} -> + Value; + false -> + throw(not_found) + end. + +-spec get(ec_dictionary:key(K), + ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Default, {ec_assoc_list, Data}) -> + case lists:keyfind(Key, 1, Data) of + {Key, Value} -> + Value; + false -> + Default + end. + +-spec add(ec_dictionary:key(K), ec_dictionary:value(V), + Object::dictionary(K, V)) -> + dictionary(K, V). +add(Key, Value, {ec_assoc_list, _Data}=Dict) -> + {ec_assoc_list, Rest} = remove(Key,Dict), + {ec_assoc_list, [{Key, Value} | Rest ]}. + +-spec remove(ec_dictionary:key(K), Object::dictionary(K, _V)) -> + dictionary(K, _V). +remove(Key, {ec_assoc_list, Data}) -> + {ec_assoc_list, lists:keydelete(Key, 1, Data)}. + +-spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). +has_value(Value, {ec_assoc_list, Data}) -> + lists:keymember(Value, 2, Data). + +-spec size(Object::dictionary(_K, _V)) -> integer(). +size({ec_assoc_list, Data}) -> + length(Data). + +-spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), + ec_dictionary:value(V)}]. +to_list({ec_assoc_list, Data}) -> + Data. + +-spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> + dictionary(K, V). +from_list(List) when is_list(List) -> + {ec_assoc_list, List}. + +-spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. +keys({ec_assoc_list, Data}) -> + lists:map(fun({Key, _Value}) -> + Key + end, Data). diff --git a/src/ec_dict.erl b/src/ec_dict.erl new file mode 100644 index 0000000..b760e92 --- /dev/null +++ b/src/ec_dict.erl @@ -0,0 +1,107 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% This provides an implementation of the ec_dictionary type using +%%% erlang dicts as a base. The function documentation for +%%% ec_dictionary applies here as well. +%%% @end +%%% @see ec_dictionary +%%% @see dict +%%%------------------------------------------------------------------- +-module(ec_dict). + +-behaviour(ec_dictionary). + +%% API +-export([new/0, + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). + +-export_type([dictionary/2]). + +%%%=================================================================== +%%% Types +%%%=================================================================== +-opaque dictionary(_K, _V) :: dict(). + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec new() -> dictionary(_K, _V). +new() -> + dict:new(). + +-spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). +has_key(Key, Data) -> + dict:is_key(Key, Data). + +-spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Data) -> + case dict:find(Key, Data) of + {ok, Value} -> + Value; + error -> + throw(not_found) + end. + +-spec get(ec_dictionary:key(K), + ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Default, Data) -> + case dict:find(Key, Data) of + {ok, Value} -> + Value; + error -> + Default + end. + +-spec add(ec_dictionary:key(K), ec_dictionary:value(V), + Object::dictionary(K, V)) -> + dictionary(K, V). +add(Key, Value, Data) -> + dict:store(Key, Value, Data). + +-spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> + dictionary(K, V). +remove(Key, Data) -> + dict:erase(Key, Data). + +-spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). +has_value(Value, Data) -> + dict:fold(fun(_, NValue, _) when NValue == Value -> + true; + (_, _, Acc) -> + Acc + end, + false, + Data). + +-spec size(Object::dictionary(_K, _V)) -> integer(). +size(Data) -> + dict:size(Data). + +-spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), + ec_dictionary:value(V)}]. +to_list(Data) -> + dict:to_list(Data). + +-spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> + dictionary(K, V). +from_list(List) when is_list(List) -> + dict:from_list(List). + +-spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. +keys(Dict) -> + dict:fetch_keys(Dict). diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl new file mode 100644 index 0000000..0e0e11b --- /dev/null +++ b/src/ec_dictionary.erl @@ -0,0 +1,158 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% A module that supports association of keys to values. A map cannot +%%% contain duplicate keys; each key can map to at most one value. +%%% +%%% This interface is a member of the Erlware Commons Library. +%%% @end +%%%------------------------------------------------------------------- +-module(ec_dictionary). + +%%% Behaviour Callbacks +-export([behaviour_info/1]). + +%% API +-export([new/1, + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/2, + keys/1]). + +-export_type([dictionary/2, + key/1, + value/1]). + +%%%=================================================================== +%%% Types +%%%=================================================================== + +-record(dict_t, + {callback, + data}). + +-opaque dictionary(_K, _V) :: #dict_t{}. +-type key(T) :: T. +-type value(T) :: T. + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc export the behaviour callbacks for this type +%% @private +behaviour_info(callbacks) -> + [{new, 0}, + {has_key, 2}, + {get, 2}, + {add, 3}, + {remove, 2}, + {has_value, 2}, + {size, 1}, + {to_list, 1}, + {from_list, 1}, + {keys, 1}]; +behaviour_info(_) -> + undefined. + +%% @doc create a new dictionary object from the specified module. The +%% module should implement the dictionary behaviour. +%% +%% @param ModuleName The module name. +-spec new(module()) -> dictionary(_K, _V). +new(ModuleName) when is_atom(ModuleName) -> + #dict_t{callback = ModuleName, data = ModuleName:new()}. + +%% @doc check to see if the dictionary provided has the specified key. +%% +%% @param Dict The dictory object to check +%% @param Key The key to check the dictionary for +-spec has_key(key(K), dictionary(K, _V)) -> boolean(). +has_key(Key, #dict_t{callback = Mod, data = Data}) -> + Mod:has_key(Key, Data). + +%% @doc given a key return that key from the dictionary. If the key is +%% not found throw a 'not_found' exception. +%% +%% @param Dict The dictionary object to return the value from +%% @param Key The key requested +%% @throws not_found when the key does not exist +-spec get(key(K), dictionary(K, V)) -> value(V). +get(Key, #dict_t{callback = Mod, data = Data}) -> + Mod:get(Key, Data). + +%% @doc given a key return that key from the dictionary. If the key is +%% not found then the default value is returned. +%% +%% @param Dict The dictionary object to return the value from +%% @param Key The key requested +%% @param Default The value that will be returned if no value is found +%% in the database. +-spec get(key(K), value(V), dictionary(K, V)) -> value(V). +get(Key, Default, #dict_t{callback = Mod, data = Data}) -> + Mod:get(Key, Default, Data). + +%% @doc add a new value to the existing dictionary. Return a new +%% dictionary containing the value. +%% +%% @param Dict the dictionary object to add too +%% @param Key the key to add +%% @param Value the value to add +-spec add(key(K), value(V), dictionary(K, V)) -> dictionary(K, V). +add(Key, Value, #dict_t{callback = Mod, data = Data} = Dict) -> + Dict#dict_t{data = Mod:add(Key, Value, Data)}. + +%% @doc Remove a value from the dictionary returning a new dictionary +%% with the value removed. +%% +%% @param Dict the dictionary object to remove the value from +%% @param Key the key of the key/value pair to remove +-spec remove(key(K), dictionary(K, V)) -> dictionary(K, V). +remove(Key, #dict_t{callback = Mod, data = Data} = Dict) -> + Dict#dict_t{data = Mod:remove(Key, Data)}. + +%% @doc Check to see if the value exists in the dictionary +%% +%% @param Dict the dictionary object to check +%% @param Value The value to check if exists +-spec has_value(value(V), dictionary(_K, V)) -> boolean(). +has_value(Value, #dict_t{callback = Mod, data = Data}) -> + Mod:has_value(Value, Data). + +%% @doc return the current number of key value pairs in the dictionary +%% +%% @param Dict the object return the size for. +-spec size(dictionary(_K, _V)) -> integer(). +size(#dict_t{callback = Mod, data = Data}) -> + Mod:size(Data). + +%% @doc Return the contents of this dictionary as a list of key value +%% pairs. +%% +%% @param Dict the base dictionary to make use of. +-spec to_list(Dict::dictionary(K, V)) -> [{key(K), value(V)}]. +to_list(#dict_t{callback = Mod, data = Data}) -> + Mod:to_list(Data). + +%% @doc Create a new dictionary, of the specified implementation using +%% the list provided as the starting contents. +%% +%% @param ModuleName the type to create the dictionary from +%% @param List The list of key value pairs to start with +-spec from_list(module(), [{key(K), value(V)}]) -> dictionary(K, V). +from_list(ModuleName, List) when is_list(List) -> + #dict_t{callback = ModuleName, data = ModuleName:from_list(List)}. + +%% @doc Return the keys of this dictionary as a list +%% +%% @param Dict the base dictionary to make use of. +-spec keys(Dict::dictionary(K, _V)) -> [key(K)]. +keys(#dict_t{callback = Mod, data = Data}) -> + Mod:keys(Data). diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl new file mode 100644 index 0000000..d9fa761 --- /dev/null +++ b/src/ec_gb_trees.erl @@ -0,0 +1,223 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% This provides an implementation of the type ec_dictionary using +%%% gb_trees as a backin +%%% @end +%%% @see ec_dictionary +%%% @see gb_trees +%%%------------------------------------------------------------------- +-module(ec_gb_trees). + +-behaviour(ec_dictionary). + +%% API +-export([new/0, + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). + +-export_type([dictionary/2]). + +%%%=================================================================== +%%% Types +%%%=================================================================== +-opaque dictionary(K, V) :: {non_neg_integer(), ec_gb_tree_node(K, V)}. + +-type ec_gb_tree_node(K, V) :: 'nil' | {K, V, + ec_gb_tree_node(K, V), + ec_gb_tree_node(K, V)}. + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc create a new dictionary object from the specified module. The +%% module should implement the dictionary behaviour. In the clause +%% where an existing object is passed in new empty dictionary of the +%% same implementation is created and returned. +%% +%% @param ModuleName|Object The module name or existing dictionary object. +-spec new() -> dictionary(_K, _V). +new() -> + gb_trees:empty(). + +%% @doc check to see if the dictionary provided has the specified key. +%% +%% @param Object The dictory object to check +%% @param Key The key to check the dictionary for +-spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). +has_key(Key, Data) -> + case gb_trees:lookup(Key, Data) of + {value, _Val} -> + true; + none -> + false + end. + +%% @doc given a key return that key from the dictionary. If the key is +%% not found throw a 'not_found' exception. +%% +%% @param Object The dictionary object to return the value from +%% @param Key The key requested +%% @throws not_found when the key does not exist +-spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Data) -> + case gb_trees:lookup(Key, Data) of + {value, Value} -> + Value; + none -> + throw(not_found) + end. + +-spec get(ec_dictionary:key(K), + ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Default, Data) -> + case gb_trees:lookup(Key, Data) of + {value, Value} -> + Value; + none -> + Default + end. + +%% @doc add a new value to the existing dictionary. Return a new +%% dictionary containing the value. +%% +%% @param Object the dictionary object to add too +%% @param Key the key to add +%% @param Value the value to add +-spec add(ec_dictionary:key(K), ec_dictionary:value(V), + Object::dictionary(K, V)) -> + dictionary(K, V). +add(Key, Value, Data) -> + gb_trees:enter(Key, Value, Data). + +%% @doc Remove a value from the dictionary returning a new dictionary +%% with the value removed. +%% +%% @param Object the dictionary object to remove the value from +%% @param Key the key of the key/value pair to remove +-spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> + dictionary(K, V). +remove(Key, Data) -> + gb_trees:delete_any(Key, Data). + +%% @doc Check to see if the value exists in the dictionary +%% +%% @param Object the dictionary object to check +%% @param Value The value to check if exists +-spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). +has_value(Value, Data) -> + lists:member(Value, gb_trees:values(Data)). + +%% @doc return the current number of key value pairs in the dictionary +%% +%% @param Object the object return the size for. +-spec size(Object::dictionary(_K, _V)) -> integer(). +size(Data) -> + gb_trees:size(Data). + +-spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), + ec_dictionary:value(V)}]. +to_list(Data) -> + gb_trees:to_list(Data). + +-spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> + dictionary(K, V). +from_list(List) when is_list(List) -> + lists:foldl(fun({Key, Value}, Dict) -> + gb_trees:enter(Key, Value, Dict) + end, + gb_trees:empty(), + List). + +-spec keys(dictionary(K,_V)) -> [ec_dictionary:key(K)]. +keys(Data) -> + gb_trees:keys(Data). + +%%%=================================================================== +%%% Tests +%%%=================================================================== + + +-ifndef(NOTEST). +-include_lib("eunit/include/eunit.hrl"). + +%% For me unit testing initially is about covering the obvious case. A +%% check to make sure that what you expect the tested functionality to +%% do, it actually does. As time goes on and people detect bugs you +%% add tests for those specific problems to the unit test suit. +%% +%% However, when getting started you can only test your basic +%% expectations. So here are the expectations I have for the add +%% functionality. +%% +%% 1) I can put arbitrary terms into the dictionary as keys +%% 2) I can put arbitrary terms into the dictionary as values +%% 3) When I put a value in the dictionary by a key, I can retrieve +%% that same value +%% 4) When I put a different value in the dictionary by key it does +%% not change other key value pairs. +%% 5) When I update a value the new value in available by the new key +%% 6) When a value does not exist a not found exception is created + +add_test() -> + Dict0 = ec_dictionary:new(ec_gb_trees), + + Key1 = foo, + Key2 = [1, 3], + Key3 = {"super"}, + Key4 = <<"fabulous">>, + Key5 = {"Sona", 2, <<"Zuper">>}, + + Value1 = Key5, + Value2 = Key4, + Value3 = Key2, + Value4 = Key3, + Value5 = Key1, + + Dict01 = ec_dictionary:add(Key1, Value1, Dict0), + Dict02 = ec_dictionary:add(Key3, Value3, + ec_dictionary:add(Key2, Value2, + Dict01)), + Dict1 = + ec_dictionary:add(Key5, Value5, + ec_dictionary:add(Key4, Value4, + Dict02)), + + ?assertMatch(Value1, ec_dictionary:get(Key1, Dict1)), + ?assertMatch(Value2, ec_dictionary:get(Key2, Dict1)), + ?assertMatch(Value3, ec_dictionary:get(Key3, Dict1)), + ?assertMatch(Value4, ec_dictionary:get(Key4, Dict1)), + ?assertMatch(Value5, ec_dictionary:get(Key5, Dict1)), + + + Dict2 = ec_dictionary:add(Key3, Value5, + ec_dictionary:add(Key2, Value4, Dict1)), + + + ?assertMatch(Value1, ec_dictionary:get(Key1, Dict2)), + ?assertMatch(Value4, ec_dictionary:get(Key2, Dict2)), + ?assertMatch(Value5, ec_dictionary:get(Key3, Dict2)), + ?assertMatch(Value4, ec_dictionary:get(Key4, Dict2)), + ?assertMatch(Value5, ec_dictionary:get(Key5, Dict2)), + + + ?assertThrow(not_found, ec_dictionary:get(should_blow_up, Dict2)), + ?assertThrow(not_found, ec_dictionary:get("This should blow up too", + Dict2)). + + + +-endif. diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl new file mode 100644 index 0000000..71f3d23 --- /dev/null +++ b/src/ec_orddict.erl @@ -0,0 +1,107 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% This provides an implementation of the ec_dictionary type using +%%% erlang orddicts as a base. The function documentation for +%%% ec_dictionary applies here as well. +%%% @end +%%% @see ec_dictionary +%%% @see orddict +%%%------------------------------------------------------------------- +-module(ec_orddict). + +-behaviour(ec_dictionary). + +%% API +-export([new/0, + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). + +-export_type([dictionary/2]). + +%%%=================================================================== +%%% Types +%%%=================================================================== +-opaque dictionary(K, V) :: [{K, V}]. + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec new() -> dictionary(_K, _V). +new() -> + orddict:new(). + +-spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). +has_key(Key, Data) -> + orddict:is_key(Key, Data). + +-spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Data) -> + case orddict:find(Key, Data) of + {ok, Value} -> + Value; + error -> + throw(not_found) + end. + +-spec get(ec_dictionary:key(K), + Default::ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). +get(Key, Default, Data) -> + case orddict:find(Key, Data) of + {ok, Value} -> + Value; + error -> + Default + end. + +-spec add(ec_dictionary:key(K), ec_dictionary:value(V), + Object::dictionary(K, V)) -> + dictionary(K, V). +add(Key, Value, Data) -> + orddict:store(Key, Value, Data). + +-spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> + dictionary(K, V). +remove(Key, Data) -> + orddict:erase(Key, Data). + +-spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). +has_value(Value, Data) -> + orddict:fold(fun(_, NValue, _) when NValue == Value -> + true; + (_, _, Acc) -> + Acc + end, + false, + Data). + +-spec size(Object::dictionary(_K, _V)) -> integer(). +size(Data) -> + orddict:size(Data). + +-spec to_list(dictionary(K, V)) -> + [{ec_dictionary:key(K), ec_dictionary:value(V)}]. +to_list(Data) -> + orddict:to_list(Data). + +-spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> + dictionary(K, V). +from_list(List) when is_list(List) -> + orddict:from_list(List). + +-spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. +keys(Dict) -> + orddict:fetch_keys(Dict). diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl new file mode 100644 index 0000000..0e962ec --- /dev/null +++ b/src/ec_rbdict.erl @@ -0,0 +1,319 @@ +%%% Copyright (c) 2008 Robert Virding. All rights reserved. +%%% +%%% Redistribution and use in source and binary forms, with or without +%%% modification, are permitted provided that the following conditions +%%% are met: +%%% +%%% 1. Redistributions of source code must retain the above copyright +%%% notice, this list of conditions and the following disclaimer. +%%% 2. Redistributions in binary form must reproduce the above copyright +%%% notice, this list of conditions and the following disclaimer in the +%%% documentation and/or other materials provided with the distribution. +%%% +%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +%%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +%%% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +%%% COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +%%% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +%%% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +%%% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +%%% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +%%% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +%%% POSSIBILITY OF SUCH DAMAGE. +%%%------------------------------------------------------------------- +%%% @copyright 2008 Robert Verding +%%% +%%% @doc +%%% +%%% Rbdict implements a Key - Value dictionary. An rbdict is a +%%% representation of a dictionary, where a red-black tree is used to +%%% store the keys and values. +%%% +%%% This module implents exactly the same interface as the module +%%% ec_dictionary but with a defined representation. One difference is +%%% that while dict considers two keys as different if they do not +%%% match (=:=), this module considers two keys as different if and +%%% only if they do not compare equal (==). +%%% +%%% The algorithms here are taken directly from Okasaki and Rbset +%%% in ML/Scheme. The interface is compatible with the standard dict +%%% interface. +%%% +%%% The following structures are used to build the the RB-dict: +%%% +%%% {r,Left,Key,Val,Right} +%%% {b,Left,Key,Val,Right} +%%% empty +%%% +%%% It is interesting to note that expanding out the first argument of +%%% l/rbalance, the colour, in store etc. is actually slower than not +%%% doing it. Measured. +%%% +%%% @end +%%% @see ec_dictionary +%%%------------------------------------------------------------------- +-module(ec_rbdict). + +-behaviour(ec_dictionary). + +%% Standard interface. +-export([add/3, from_list/1, get/2, get/3, has_key/2, + has_value/2, new/0, remove/2, size/1, to_list/1, + keys/1]). + +-export_type([dictionary/2]). + +%%%=================================================================== +%%% Types +%%%=================================================================== + +-opaque dictionary(K, V) :: empty | {color(), + dictionary(K, V), + ec_dictionary:key(K), + ec_dictionary:value(V), + dictionary(K, V)}. + +-type color() :: r | b. + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec new() -> dictionary(_K, _V). +new() -> empty. + +-spec has_key(ec_dictionary:key(K), dictionary(K, _V)) -> boolean(). +has_key(_, empty) -> + false; +has_key(K, {_, Left, K1, _, _}) when K < K1 -> + has_key(K, Left); +has_key(K, {_, _, K1, _, Right}) when K > K1 -> + has_key(K, Right); +has_key(_, {_, _, _, _, _}) -> + true. + +-spec get(ec_dictionary:key(K), dictionary(K, V)) -> ec_dictionary:value(V). +get(_, empty) -> + throw(not_found); +get(K, {_, Left, K1, _, _}) when K < K1 -> + get(K, Left); +get(K, {_, _, K1, _, Right}) when K > K1 -> + get(K, Right); +get(_, {_, _, _, Val, _}) -> + Val. + +-spec get(ec_dictionary:key(K), + ec_dictionary:value(V), + dictionary(K, V)) -> ec_dictionary:value(V). +get(_, Default, empty) -> + Default; +get(K, Default, {_, Left, K1, _, _}) when K < K1 -> + get(K, Default, Left); +get(K, Default, {_, _, K1, _, Right}) when K > K1 -> + get(K, Default, Right); +get(_, _, {_, _, _, Val, _}) -> + Val. + +-spec add(ec_dicitonary:key(K), ec_dictionary:value(V), + dictionary(K, V)) -> dictionary(K, V). +add(Key, Value, Dict) -> + {_, L, K1, V1, R} = add1(Key, Value, Dict), + {b, L, K1, V1, R}. + +-spec remove(ec_dictionary:key(K), dictionary(K, V)) -> dictionary(K, V). +remove(Key, Dictionary) -> + {Dict1, _} = erase_aux(Key, Dictionary), Dict1. + +-spec has_value(ec_dictionary:value(V), dictionary(_K, V)) -> boolean(). +has_value(Value, Dict) -> + fold(fun (_, NValue, _) when NValue == Value -> true; + (_, _, Acc) -> Acc + end, + false, Dict). + +-spec size(dictionary(_K, _V)) -> integer(). +size(T) -> + size1(T). + +-spec to_list(dictionary(K, V)) -> + [{ec_dictionary:key(K), ec_dictionary:value(V)}]. +to_list(T) -> + to_list(T, []). + +-spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> + dictionary(K, V). +from_list(L) -> + lists:foldl(fun ({K, V}, D) -> + add(K, V, D) + end, new(), + L). + +-spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. +keys(Dict) -> + keys(Dict, []). + +%%%=================================================================== +%%% Enternal functions +%%%=================================================================== +-spec keys(dictionary(K, _V), [ec_dictionary:key(K)]) -> + [ec_dictionary:key(K)]. +keys(empty, Tail) -> + Tail; +keys({_, L, K, _, R}, Tail) -> + keys(L, [K | keys(R, Tail)]). + + +-spec erase_aux(ec_dictionary:key(K), dictionary(K, V)) -> + {dictionary(K, V), boolean()}. +erase_aux(_, empty) -> + {empty, false}; +erase_aux(K, {b, A, Xk, Xv, B}) -> + if K < Xk -> + {A1, Dec} = erase_aux(K, A), + if Dec -> + unbalright(b, A1, Xk, Xv, B); + true -> + {{b, A1, Xk, Xv, B}, false} + end; + K > Xk -> + {B1, Dec} = erase_aux(K, B), + if Dec -> + unballeft(b, A, Xk, Xv, B1); + true -> + {{b, A, Xk, Xv, B1}, false} + end; + true -> + case B of + empty -> + blackify(A); + _ -> + {B1, {Mk, Mv}, Dec} = erase_min(B), + if Dec -> + unballeft(b, A, Mk, Mv, B1); + true -> + {{b, A, Mk, Mv, B1}, false} + end + end + end; +erase_aux(K, {r, A, Xk, Xv, B}) -> + if K < Xk -> + {A1, Dec} = erase_aux(K, A), + if Dec -> + unbalright(r, A1, Xk, Xv, B); + true -> + {{r, A1, Xk, Xv, B}, false} + end; + K > Xk -> + {B1, Dec} = erase_aux(K, B), + if Dec -> + unballeft(r, A, Xk, Xv, B1); + true -> + {{r, A, Xk, Xv, B1}, false} + end; + true -> + case B of + empty -> + {A, false}; + _ -> + {B1, {Mk, Mv}, Dec} = erase_min(B), + if Dec -> + unballeft(r, A, Mk, Mv, B1); + true -> + {{r, A, Mk, Mv, B1}, false} + end + end + end. + +-spec erase_min(dictionary(K, V)) -> + {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean}. +erase_min({b, empty, Xk, Xv, empty}) -> + {empty, {Xk, Xv}, true}; +erase_min({b, empty, Xk, Xv, {r, A, Yk, Yv, B}}) -> + {{b, A, Yk, Yv, B}, {Xk, Xv}, false}; +erase_min({b, empty, _, _, {b, _, _, _, _}}) -> + exit(boom); +erase_min({r, empty, Xk, Xv, A}) -> + {A, {Xk, Xv}, false}; +erase_min({b, A, Xk, Xv, B}) -> + {A1, Min, Dec} = erase_min(A), + if Dec -> + {T, Dec1} = unbalright(b, A1, Xk, Xv, B), + {T, Min, Dec1}; + true -> {{b, A1, Xk, Xv, B}, Min, false} + end; +erase_min({r, A, Xk, Xv, B}) -> + {A1, Min, Dec} = erase_min(A), + if Dec -> + {T, Dec1} = unbalright(r, A1, Xk, Xv, B), + {T, Min, Dec1}; + true -> {{r, A1, Xk, Xv, B}, Min, false} + end. + +blackify({r, A, K, V, B}) -> {{b, A, K, V, B}, false}; +blackify(Node) -> {Node, true}. + +unballeft(r, {b, A, Xk, Xv, B}, Yk, Yv, C) -> + {lbalance(b, {r, A, Xk, Xv, B}, Yk, Yv, C), false}; +unballeft(b, {b, A, Xk, Xv, B}, Yk, Yv, C) -> + {lbalance(b, {r, A, Xk, Xv, B}, Yk, Yv, C), true}; +unballeft(b, {r, A, Xk, Xv, {b, B, Yk, Yv, C}}, Zk, Zv, + D) -> + {{b, A, Xk, Xv, + lbalance(b, {r, B, Yk, Yv, C}, Zk, Zv, D)}, + false}. + +unbalright(r, A, Xk, Xv, {b, B, Yk, Yv, C}) -> + {rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), false}; +unbalright(b, A, Xk, Xv, {b, B, Yk, Yv, C}) -> + {rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), true}; +unbalright(b, A, Xk, Xv, + {r, {b, B, Yk, Yv, C}, Zk, Zv, D}) -> + {{b, rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), Zk, Zv, + D}, + false}. + +-spec fold(fun(), dictionary(K, V), dictionary(K, V)) -> dictionary(K, V). +fold(_, Acc, empty) -> Acc; +fold(F, Acc, {_, A, Xk, Xv, B}) -> + fold(F, F(Xk, Xv, fold(F, Acc, B)), A). + +add1(K, V, empty) -> {r, empty, K, V, empty}; +add1(K, V, {C, Left, K1, V1, Right}) when K < K1 -> + lbalance(C, add1(K, V, Left), K1, V1, Right); +add1(K, V, {C, Left, K1, V1, Right}) when K > K1 -> + rbalance(C, Left, K1, V1, add1(K, V, Right)); +add1(K, V, {C, L, _, _, R}) -> {C, L, K, V, R}. + +size1(empty) -> 0; +size1({_, L, _, _, R}) -> size1(L) + size1(R) + 1. + +to_list(empty, List) -> List; +to_list({_, A, Xk, Xv, B}, List) -> + to_list(A, [{Xk, Xv} | to_list(B, List)]). + +%% Balance a tree afer (possibly) adding a node to the left/right. +-spec lbalance(color(), dictionary(K, V), + ec_dictinary:key(K), ec_dictionary:value(V), + dictionary(K, V)) -> + dictionary(K, V). +lbalance(b, {r, {r, A, Xk, Xv, B}, Yk, Yv, C}, Zk, Zv, + D) -> + {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; +lbalance(b, {r, A, Xk, Xv, {r, B, Yk, Yv, C}}, Zk, Zv, + D) -> + {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; +lbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. + +-spec rbalance(color(), dictionary(K, V), + ec_dictinary:key(K), ec_dictionary:value(V), + dictionary(K, V)) -> + dictionary(K, V). +rbalance(b, A, Xk, Xv, + {r, {r, B, Yk, Yv, C}, Zk, Zv, D}) -> + {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; +rbalance(b, A, Xk, Xv, + {r, B, Yk, Yv, {r, C, Zk, Zv, D}}) -> + {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; +rbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. diff --git a/test/ec_dictionary_proper.erl b/test/ec_dictionary_proper.erl new file mode 100644 index 0000000..d30f542 --- /dev/null +++ b/test/ec_dictionary_proper.erl @@ -0,0 +1,223 @@ +%% compile with +%% erl -pz ebin --make +%% start test with +%% erl -pz ebin -pz test +%% proper:module(ec_dictionary_proper). +-module(ec_dictionary_proper). + +-export([my_dict/0, dict/1, sym_dict/0, sym_dict/1, gb_tree/0, gb_tree/1, sym_dict2/0]). + +-include_lib("proper/include/proper.hrl"). + + +%%------------------------------------------------------------------------------ +%% Properties +%%------------------------------------------------------------------------------ + +prop_size_increases_with_new_key() -> + ?FORALL({Dict,K}, {sym_dict(),integer()}, + begin + Size = ec_dictionary:size(Dict), + case ec_dictionary:has_key(K,Dict) of + true -> + Size == ec_dictionary:size(ec_dictionary:add(K,0,Dict)); + false -> + (Size + 1) == ec_dictionary:size(ec_dictionary:add(K,0,Dict)) + end + end). + +prop_size_decrease_when_removing() -> + ?FORALL({Dict,K}, {sym_dict(),integer()}, + begin + Size = ec_dictionary:size(Dict), + case ec_dictionary:has_key(K,Dict) of + false -> + Size == ec_dictionary:size(ec_dictionary:remove(K,Dict)); + true -> + (Size - 1) == ec_dictionary:size(ec_dictionary:remove(K,Dict)) + end + end). + +prop_get_after_add_returns_correct_value() -> + ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, + begin + try ec_dictionary:get(K,ec_dictionary:add(K,V,Dict)) of + V -> + true; + _ -> + false + catch + _:_ -> + false + end + end). + +prop_get_default_returns_correct_value() -> + ?FORALL({Dict,K1,K2,V,Default}, + {sym_dict(),key(),key(),value(),value()}, + begin + NewDict = ec_dictionary:add(K1,V, Dict), + %% In the unlikely event that keys that are the same + %% are generated + case ec_dictionary:has_key(K2, NewDict) of + true -> + true; + false -> + ec_dictionary:get(K2, Default, NewDict) == Default + end + end). + + +prop_add_does_not_change_values_for_other_keys() -> + ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, + begin + Keys = ec_dictionary:keys(Dict), + ?IMPLIES(not lists:member(K,Keys), + begin + Dict2 = ec_dictionary:add(K,V,Dict), + try lists:all(fun(B) -> B end, + [ ec_dictionary:get(Ka,Dict) == + ec_dictionary:get(Ka,Dict2) || + Ka <- Keys ]) of + Bool -> Bool + catch + throw:not_found -> true + end + end) + end). + + + +prop_key_is_present_after_add() -> + ?FORALL({Dict,K,V}, {sym_dict(),integer(),integer()}, + begin + ec_dictionary:has_key(K,ec_dictionary:add(K,V,Dict)) end). + +prop_value_is_present_after_add() -> + ?FORALL({Dict,K,V}, {sym_dict(),integer(),integer()}, + begin + ec_dictionary:has_value(V,ec_dictionary:add(K,V,Dict)) + end). + +prop_to_list_matches_get() -> + ?FORALL(Dict,sym_dict(), + begin + %% Dict = eval(SymDict), + %% io:format("SymDict: ~p~n",[proper_symb:symbolic_seq(SymDict)]), + ToList = ec_dictionary:to_list(Dict), + %% io:format("ToList:~p~n",[ToList]), + GetList = + try [ {K,ec_dictionary:get(K,Dict)} || {K,_V} <- ToList ] of + List -> List + catch + throw:not_found -> key_not_found + end, + %% io:format("~p == ~p~n",[ToList,GetList]), + lists:sort(ToList) == lists:sort(GetList) + end). + +prop_value_changes_after_update() -> + ?FORALL({Dict, K1, V1, V2}, + {sym_dict(), + key(), value(), value()}, + begin + Dict1 = ec_dictionary:add(K1, V1, Dict), + Dict2 = ec_dictionary:add(K1, V2, Dict1), + V1 == ec_dictionary:get(K1, Dict1) andalso + V2 == ec_dictionary:get(K1, Dict2) + end). + +prop_remove_removes_only_one_key() -> + ?FORALL({Dict,K}, + {sym_dict(),key()}, + begin + {KeyGone,Dict2} = case ec_dictionary:has_key(K,Dict) of + true -> + D2 = ec_dictionary:remove(K,Dict), + {ec_dictionary:has_key(K,D2) == false, + D2}; + false -> + {true,ec_dictionary:remove(K,Dict)} + end, + OtherEntries = [ KV || {K1,_} = KV <- ec_dictionary:to_list(Dict), + K1 /= K ], + KeyGone andalso + lists:sort(OtherEntries) == lists:sort(ec_dictionary:to_list(Dict2)) + end). + +prop_from_list() -> + ?FORALL({Dict,DictType}, + {sym_dict(),dictionary()}, + begin + List = ec_dictionary:to_list(Dict), + D2 = ec_dictionary:from_list(DictType,List), + List2 = ec_dictionary:to_list(D2), + lists:sort(List) == lists:sort(List2) + end). + + +%%----------------------------------------------------------------------------- +%% Generators +%%----------------------------------------------------------------------------- + +key() -> union([integer(),atom()]). + +value() -> union([integer(),atom(),binary(),boolean(),string()]). + + +my_dict() -> + ?SIZED(N,dict(N)). + + +dict(0) -> + ec_dictionary:new(ec_gb_trees); +dict(N) -> + ?LET(D,dict(N-1), + frequency([ + {1, dict(0)}, + {3, ec_dictionary:remove(integer(),D)}, + {6, ec_dictionary:add(integer(),integer(),D)} + ])). + +sym_dict() -> + ?SIZED(N,sym_dict(N)). + +%% This symbolic generator will create a random instance of a ec_dictionary +%% that will be used in the properties. +sym_dict(0) -> + ?LET(Dict,dictionary(), + {'$call',ec_dictionary,new,[Dict]}); +sym_dict(N) -> + ?LAZY( + frequency([ + {1, sym_dict(0)}, + {3, {'$call',ec_dictionary,remove,[key(),sym_dict(N-1)]}}, + {6, {'$call',ec_dictionary,add,[value(),value(),sym_dict(N-1)]}} + ]) + ). + +dictionary() -> + union([ec_gb_trees,ec_assoc_list,ec_dict,ec_orddict]). + +sym_dict2() -> + ?SIZED(N,sym_dict2(N)). + +sym_dict2(0) -> + {call,ec_dictionary,new,[ec_gb_trees]}; +sym_dict2(N) -> + D = dict(N-1), + frequency([ + {1, {call,ec_dictionary,remove,[integer(),D]}}, + {2, {call,ec_dictionary,add,[integer(),integer(),D]}} + ]). + + +%% For the tutorial. +gb_tree() -> + ?SIZED(N,gb_tree(N)). + +gb_tree(0) -> + gb_trees:empty(); +gb_tree(N) -> + gb_trees:enter(key(),value(),gb_tree(N-1)). + diff --git a/test/mock.erl b/test/mock.erl new file mode 100644 index 0000000..ad7c6bd --- /dev/null +++ b/test/mock.erl @@ -0,0 +1,10 @@ +-module(mock). + +-export([new_dictionary/0]). + +new_dictionary() -> + meck:new(ec_dictionary_proper), + meck:expect(ec_dictionary_proper, dictionary, fun() -> + proper_types:union([ec_dict]) + end). + From 2b320a34a562fcb18243e96b632c9a77c1415a83 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 14 Oct 2011 12:29:37 -0500 Subject: [PATCH 003/240] add comprehensive readme to the system Signed-off-by: Jordan Wilberding --- README.md | 534 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d0bc4f --- /dev/null +++ b/README.md @@ -0,0 +1,534 @@ +ERESYE - ERlang Expert SYstem Engine +======================================== + +Introduction +------------ + +This article describe how to write a simple Artificial Intelligence +application with Erlang, by using a *rule production system*. + +To reach this objective, we will exploit the **ERESYE** tool, an +Erlang Inference Engine that allows rule-based systems to be written +directly in Erlang. + +As it is widely known, a rule-based system is composed by a +**knowledge base**, which stores a set of *facts* representing the +'universe of discourse' of a given application, and a set of +**production rules**, which are used to infer knowledge and/or reason +about the knowledge. A rule is activated when one or more facts match +the template(s) given in the rule declaration: in such a case, the +body of the rule contains a code that is thus executed + +In ERESYE, *facts* are expressed by means of Erlang tuples or records, +while rules are written using standard Erlang function clauses, whose +declaration reports, in the clause head, the facts or fact templates +that have to be matched for the rule to be activated and executed. + +For more information about ERESYE please refer to the paper docs directory. + +For more information about rule-based inference engines and expert +systems, you can refer to the book: *S. Russell and +P. Norvig. **Artificial Intelligence: A Modern Approach/2E.** Prentice +Hall, 2003.* + +To write an AI application with ERESYE the following steps have to be +performed: + +1. Indentify your universe of discourse and determine the facts that + have to be used to represent such a world; + +2. Indentify the rules that you need and write them by using, e.g. + first-order-logic predicates or even natural language; + +3. Implement the system by writing your rules as Erlang function + clauses, according to the modality required by ERESYE. + + +The Application: the Domain of Relatives +---------------------------------------- + +We will design a system able to derive new knowledge using some +inference rules and starting from a small set; as a sample +application, we chose the domain of relatives: we will start from some +base concepts, such as *parent*, *male* and *female*, and then, by +means of a proper set of rules, we will derive the concepts of +*mother*, *father*, *sister*, *brother*, *grandmother* and +*grandfather*. + +According to the list above, we will first derive the facts that will be +used to represent our concepts. Given the set of relationships above, they +will be represented by means of the following facts: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#ConceptFact / Erlang tuple
1X is male{male, X}
2X is female{female, X}
3X is Y's parent{parent, X, Y}
4X is Y's mother{mother, X, Y}
5X is Y's father{father, X, Y}
6X is Y's sister{sister, X, Y}
7X is Y's brother{brother, X, Y}
8X is Y's grandmother{grandmother, X, Y}
9X is Y's grandfather{grandfather, X, Y}
+ +Concepts 1, 2 and 3 will be used as a base to derive the other ones. + +Deriving new concepts by means of rules +--------------------------------------- + +#### Concept: mother + +The rule to derive the concept of mother is quite +straightforward: + + if X is female and X is Y's parent then X is Y's mother. + +From the point of view of ERESYE, since knowledge is stored in the +*knowledge base* of the engine, the rule above is translated into the +following one: *if the facts {female, X} and {parent, X, Y} are +*asserted* in the knowledge base, then we assert the fact {mother, X, +Y}. + +The rule *mother* can be thus written as follows: + + %% + %% if (X is female) and (X is Y's parent) then (X is Y's mother) + %% + mother (Engine, {female, X}, {parent, X, Y}) -> + eresye:assert (Engine, {mother, X, Y}). + + +#### Concept: father + +This concept can be easily derived by means of the following rule: + + %% + %% if (X is male) and (X is Y's parent) then (X is Y's father) + %% + father (Engine, {male, X}, {parent, X, Y}) -> + eresye:assert (Engine, {father, X, Y}). + + +#### Concept: sister + + This concept can be expressed by the following rule: + + if Y and Z have the same parent and Z is female, then Z + is the Y's sister. + +The ERESYE rule used to map this concept is: + + %% + %% if (Y and Z have the same parent X) and (Z is female) + %% then (Z is Y's sister) + %% + sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> + eresye:assert (Engine, {sister, Z, Y}). + + +Please note the guard, which is needed to ensure that when Y and Z are +bound to the same value, the rule is not activated (indeed this is +possible since the same fact can match both the first and second +'parent' pattern). + +#### Concept: brother + +Given the previous one, this concept is now quite simple to +implement: + + + %% + %% if (Y and Z have the same parent X) and (Z is male) + %% then (Z is Y's brother) + %% + brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> + eresye:assert (Engine, {brother, Z, Y}). + + +#### Concepts: grandmother and grandfather + +The former concept can be expressed by means of the rule: + + if X is Y's mother and Y is Z's parent, then X is Z's + grandmother.* The latter concept is now obvious. + +Both can be implemented using the following ERESYE rules: + + %% + %% if (X is Y's mother) and (Y is Z's parent) + %% then (X is Z's grandmother) + %% + grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandmother, X, Z}). + + %% + %% if (X is Y's father) and (Y is Z's parent) + %% then (X is Z's grandfather) + %% + grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandfather, X, Z}). + + +Instantiating the Engine and Populating the Knowledge Base +---------------------------------------------------------- + +After writing the rules, we need to: + +- instantiate the engine; +- add the rules above to the engine; +- populate the knowledge base with a set of initial facts. + +We do this in the function *start* below: + + start () -> + eresye:start (relatives), + lists:foreach (fun (X) -> + eresye:add_rule (relatives, {?MODULE, X}) + end, + [mother, father, brother, sister, + grandfather, grandmother]), + + eresye:assert (relatives, + [{male, bob}, {male, corrado}, {male, mark}, {male, caesar}, + {female, alice}, {female, sara}, {female, jane}, {female, anna}, + {parent, jane, bob}, {parent, corrado, bob}, + {parent, jane, mark}, {parent, corrado, mark}, + {parent, jane, alice}, {parent, corrado, alice}, + {parent, bob, caesar}, {parent, bob, anna}, + {parent, sara, casear}, {parent, sara, anna}]), + ok. + +As the listing reports, creating a new ERESYE engine implies to call +the function *eresye:start/1*, giving the name of the engine to be +created + +Then, we have to add the rules to the engine by using the function +*eresye:add_rule/2*: it takes two arguments, the name of the engine +and a tuple representing the function in the form *{Module, +FuncName}*; obviously the function *Module:FuncName* must be +exported. Function *add_rule* has to be called for each rule that has +to be added; for this reason, the code above has an iteration over the +list of rules written before. + +Finally, we populate the inference engine with a set of sample facts +by giving them, in a list, to the function *eresye:assert/2*. To test +our rules, we considered the relationships in the Figure below and +assert only the facts for *male*, *female* and *parent*. + +Testing the application +----------------------- + +The final complete code of our AI application is thus the following: + + + %%% + %%% relatives.erl + %%% + -module (relatives). + -compile ([export_all]). + + %% + %% if (X is female) and (X is Y's parent) then (X is Y's mother) + %% + mother (Engine, {female, X}, {parent, X, Y}) -> + eresye:assert (Engine, {mother, X, Y}). + + + %% + %% if (X is male) and (X is Y's parent) then (X is Y's father) + %% + father (Engine, {male, X}, {parent, X, Y}) -> + eresye:assert (Engine, {father, X, Y}). + + + + %% + %% if (Y and Z have the same parent X) and (Z is female) + %% then (Z is Y's sister) + %% + sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> + eresye:assert (Engine, {sister, Z, Y}). + + + + %% + %% if (Y and Z have the same parent X) and (Z is male) + %% then (Z is Y's brother) + %% + brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> + eresye:assert (Engine, {brother, Z, Y}). + + + %% + %% if (X is Y's father) and (Y is Z's parent) + %% then (X is Z's grandfather) + %% + grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandfather, X, Z}). + + + %% + %% if (X is Y's mother) and (Y is Z's parent) + %% then (X is Z's grandmother) + %% + grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandmother, X, Z}). + + start () -> + eresye:start (relatives), + lists:foreach (fun (X) -> + eresye:add_rule (relatives, {?MODULE, X}) + end, + [mother, father, + brother, sister, + grandfather, grandmother]), + + eresye:assert (relatives, + [{male, bob}, + {male, corrado}, + {male, mark}, + {male, caesar}, + {female, alice}, + {female, sara}, + {female, jane}, + {female, anna}, + {parent, jane, bob}, + {parent, corrado, bob}, + {parent, jane, mark}, + {parent, corrado, mark}, + {parent, jane, alice}, + {parent, corrado, alice}, + {parent, bob, caesar}, + {parent, bob, anna}, + {parent, sara, casear}, + {parent, sara, anna}]), + ok. + +Now it's time to test our application: + + + Erlang (BEAM) emulator version 5.5 [source] [async-threads:0] [hipe] + + Eshell V5.5 (abort with ^G) + 1> c(relatives). + {ok,relatives} + 2> relatives:start(). + ok + 3> + +Following the call to function *relatives:start/0*, the engine is +created and populated; if no errors occurred, the rules should have +been processed and the new facts derived. To check this, we can use +the function *eresye:get_kb/1*, which returns the list of facts +asserted into the knowledge base of a given engine: + + + 4> eresye:get_kb(relatives). + [{brother,bob,mark}, + {sister,alice,bob}, + {sister,alice,mark}, + {brother,bob,alice}, + {brother,mark,alice}, + {grandmother,jane,caesar}, + {grandfather,corrado,caesar}, + {grandmother,jane,anna}, + {grandfather,corrado,anna}, + {sister,anna,caesar}, + {brother,caesar,anna}, + {sister,anna,casear}, + {mother,sara,anna}, + {mother,sara,casear}, + {parent,sara,anna}, + {father,bob,anna}, + {parent,sara,casear}, + {father,bob,caesar}, + {parent,bob,anna}, + {father,corrado,alice}, + {parent,bob,caesar}, + {mother,jane,alice}, + {parent,corrado,alice}, + {father,corrado,mark}, + {parent,jane,alice}, + {mother,jane,mark}, + {parent,corrado|...}, + {brother|...}, + {...}|...] + 5> + +The presence of facts representing concepts like *father*, *sister*, +etc., proves that the rules seems to be working as expected. + +We can however query the knowledge base using specific fact templates. +For example, if we want to know who are Alice's brothers, we can use +the function *eresye:query_kb/2* as follows: + + + 6> eresye:query_kb(relatives, {brother, '_', alice}). + [{brother,bob,alice},{brother,mark,alice}] + 7> + +The facts returned conform to the relationships depicted in the figure +above, thus proving that the rules written are really working. + +As the example shows, function *eresye:query_kb/2* takes the engine +name as the first argument, while, for the second parameter, a tuple +has to be specified, representing the fact template to be matched; in +such a tuple, the atom *'_'* plays the role of a wildcard. However, to +specify a more complex matching, a *fun* can be used as a tuple +element; this *fun* has to return a boolean value which indicates if +the element matches the template. For example, to select both Alice's +and Anna's brothers, we can use the following function call: + + + 7> eresye:query_kb(relatives, {brother, '_', fun (X) -> (X == alice) or (X == anna) end}). + [{brother,bob,alice},{brother,mark,alice},{brother,caesar,anna}] + 8> + +Deriving new concepts by means of rules +--------------------------------------- + +#### Concept: 'mother' + +The rule to derive the concept of mother is quite straightforward: + + if X is female and X is Y's parent then X is Y's mother. + +From the point of view of ERESYE, since knowledge is stored in the +*knowledge base* of the engine, the rule above is translated into the +following one: *if the facts *{female, X}* and *{parent, X, Y}* are +**asserted** in the knowledge base, then we assert the fact *{mother, +X, Y}*.* + +The rule *mother* can be thus written as follows: + + + %% + %% if (X is female) and (X is Y's parent) then (X is Y's mother) + %% + mother (Engine, {female, X}, {parent, X, Y}) -> + eresye:assert (Engine, {mother, X, Y}). + +#### Concept: 'father' + +This concept can be easily derived by means of the following rule: + + %% + %% if (X is male) and (X is Y's parent) then (X is Y's father) + %% + father (Engine, {male, X}, {parent, X, Y}) -> + eresye:assert (Engine, {father, X, Y}). + + +#### Concept: 'sister' + +This concept can be expressed by the following rule: + + if Y and Z have the same parent and Z is female, then Z is the Y's + sister. + +The ERESYE rule used to map this concept is: + + %% + %% if (Y and Z have the same parent X) and (Z is female) + %% then (Z is Y's sister) + %% + sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> + eresye:assert (Engine, {sister, Z, Y}). + +Please note the guard, which is needed to ensure that when Y and Z are +bound to the same value, the rule is not activated (indeed this is possible +since the same fact can match both the first and second +'parent' pattern). + +#### Concept: 'brother' + + Given the previous one, this concept is now quite simple to +implement: + + %% + %% if (Y and Z have the same parent X) and (Z is male) + %% then (Z is Y's brother) + %% + brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> + eresye:assert (Engine, {brother, Z, Y}). + + +#### Concepts: 'grandmother' and 'grandfather' + +The former concept can be expressed by means of the rule: + + if X is Y's mother and Y is Z's parent, then X is Z's grandmother. + +The latter concept is now obvious. Both can be implemented using the +following ERESYE rules: + + %% + %% if (X is Y's mother) and (Y is Z's parent) + %% then (X is Z's grandmother) + %% + grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandmother, X, Z}). + + %% + %% if (X is Y's father) and (Y is Z's parent) + %% then (X is Z's grandfather) + %% + grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> + eresye:assert (Engine, {grandfather, X, Z}). + + +Conclusions +----------- + +This HowTo not only shows how to use the ERESYE engine to write an AI +application, but also highlights the versatility of the Erlang language: +the characteristics of functional and symbolic programming, together with +the possibility of performing *introspection* of function declaration, +can be successfully exploited for application domains which are completely +new for Erlang but can surely be very interesting. + From 8898f93f617e8498db2d0f1eac047275a0a78a5a Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 14 Oct 2011 12:34:20 -0500 Subject: [PATCH 004/240] add date parsing and formatting support from Dale Harvey The original implementation was https://github.com/daleharvey/dh_date.git Signed-off-by: Jordan Wilberding --- ebin/erlware_commons.app | 1 + src/ec_date.erl | 580 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 581 insertions(+) create mode 100644 src/ec_date.erl diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index 0fc142e..ff59dde 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -8,6 +8,7 @@ ec_file, ec_string, ec_semver, + ec_date, ec_dictionary, ec_assoc_list, ec_dict, diff --git a/src/ec_date.erl b/src/ec_date.erl new file mode 100644 index 0000000..1eda795 --- /dev/null +++ b/src/ec_date.erl @@ -0,0 +1,580 @@ +%% @copyright Dale Harvey +%% @doc Format dates in erlang +%% +%% Licensed under the MIT license +%% +%% This module formats erlang dates in the form +%% {{Year, Month, Day}, {Hour, Minute, Second}} +%% to printable strings, using (almost) equivalent +%% formatting rules as http://uk.php.net/date +%% +%% erlang has no concept of timezone so the following +%% formats are not implemented: B e I O P T Z +%% formats c and r will also differ slightly +%% +%% See tests at bottom for examples +-module(ec_date). +-author("Dale Harvey "). + +-export([format/1, format/2]). +-export([parse/1, parse/2]). +-export([nparse/1]). + +%% These are used exclusively as guards and so the function like +%% defines make sense +-define( is_num(X), (X >= $0 andalso X =< $9) ). +-define( is_meridian(X), (X==[] orelse X==[am] orelse X==[pm]) ). +-define( is_sep(X), (X==$- orelse X==$/) ). + +-define(GREGORIAN_SECONDS_1970, 62167219200). + +-type year() :: non_neg_integer(). +-type month() :: 1..12. +-type day() :: 1..31. +-type hour() :: 0..23. +-type minute() :: 0..59. +-type second() :: 0..59. +-type daynum() :: 1..7. +-type date() :: {year(),month(),day()}. +-type time() :: {hour(),minute(),second()}. +-type datetime() :: {date(),time()}. +-type now() :: {integer(),integer(),integer()}. + +%% +%% EXPORTS +%% + +-spec format(string()) -> string(). +%% @doc format current local time as Format +format(Format) -> + format(Format, calendar:universal_time(),[]). + +-spec format(string(),datetime() | now()) -> string(). +%% @doc format Date as Format +format(Format, {_,_,_}=Now) -> + format(Format, calendar:now_to_datetime(Now), []); +format(Format, Date) -> + format(Format, Date, []). + +-spec parse(string()) -> datetime() | {error, bad_date}. +%% @doc parses the datetime from a string +parse(Date) -> + do_parse(Date, calendar:universal_time(),[]). + +-spec parse(string(),datetime() | now()) -> datetime() | {error, bad_date}. +%% @doc parses the datetime from a string +parse(Date, {_,_,_}=Now) -> + do_parse(Date, calendar:now_to_datetime(Now), []); +parse(Date, Now) -> + do_parse(Date, Now, []). + +do_parse(Date, Now, Opts) -> + case parse(tokenise(string:to_upper(Date), []), Now, Opts) of + {error, bad_date} -> + {error, bad_date}; + {D1, T1} = {{Y, M, D}, {H, M1, S}} + when is_number(Y), is_number(M), + is_number(D), is_number(H), + is_number(M1), is_number(S) -> + case calendar:valid_date(D1) of + true -> {D1, T1}; + false -> {error, bad_date} + end; + _ -> {error, bad_date} + end. + +-spec nparse(string()) -> now(). +%% @doc parses the datetime from a string into 'now' format +nparse(Date) -> + DateTime = parse(Date), + GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), + ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, + {ESeconds div 1000000, ESeconds rem 1000000, 0}. + + +%% +%% LOCAL FUNCTIONS +%% + +%% Times - 21:45, 13:45:54, 13:15PM etc +parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> + {Date, {hour(Hour, PAM), Min, Sec}}; +parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> + {Date, {hour(Hour, PAM), Min, 0}}; + +%% Dates 23/april/1963 +parse([Day,Month,Year], {_Date, Time}, _Opts) -> + {{Year, Month, Day}, Time}; +parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_sep(X) -> + {{Year, Month, Day}, Time}; + +%% Date/Times 22 Aug 2008 6:35 PM +parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso ?is_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; +parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; + +parse([Day,Month,Year,Hour,$:,Min | PAM], _Now, _Opts) + when ?is_meridian(PAM) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; +parse([Day,Month,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; + +parse(_Tokens, _Now, _Opts) -> + {error, bad_date}. + +tokenise([], Acc) -> + lists:reverse(Acc); + +tokenise([N1, N2, N3, N4 | Rest], Acc) + when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4) -> + tokenise(Rest, [ ltoi([N1, N2, N3, N4]) | Acc]); +tokenise([N1, N2 | Rest], Acc) + when ?is_num(N1), ?is_num(N2) -> + tokenise(Rest, [ ltoi([N1, N2]) | Acc]); +tokenise([N1 | Rest], Acc) + when ?is_num(N1) -> + tokenise(Rest, [ ltoi([N1]) | Acc]); + +tokenise("JANUARY"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); +tokenise("JAN"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); +tokenise("FEBUARY"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); +tokenise("FEB"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); +tokenise("MARCH"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); +tokenise("MAR"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); +tokenise("APRIL"++Rest, Acc) -> tokenise(Rest, [4 | Acc]); +tokenise("APR"++Rest, Acc) -> tokenise(Rest, [4 | Acc]); +tokenise("MAY"++Rest, Acc) -> tokenise(Rest, [5 | Acc]); +tokenise("JUNE"++Rest, Acc) -> tokenise(Rest, [6 | Acc]); +tokenise("JUN"++Rest, Acc) -> tokenise(Rest, [6 | Acc]); +tokenise("JULY"++Rest, Acc) -> tokenise(Rest, [7 | Acc]); +tokenise("JUL"++Rest, Acc) -> tokenise(Rest, [7 | Acc]); +tokenise("AUGUST"++Rest, Acc) -> tokenise(Rest, [8 | Acc]); +tokenise("AUG"++Rest, Acc) -> tokenise(Rest, [8 | Acc]); +tokenise("SEPTEMBER"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); +tokenise("SEPT"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); +tokenise("SEP"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); +tokenise("OCTOBER"++Rest, Acc) -> tokenise(Rest, [10 | Acc]); +tokenise("OCT"++Rest, Acc) -> tokenise(Rest, [10 | Acc]); +tokenise("NOVEMBER"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); +tokenise("NOVEM"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); +tokenise("NOV"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); +tokenise("DECEMBER"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); +tokenise("DECEM"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); +tokenise("DEC"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); + +tokenise([$: | Rest], Acc) -> tokenise(Rest, [ $: | Acc]); +tokenise([$/ | Rest], Acc) -> tokenise(Rest, [ $/ | Acc]); +tokenise([$- | Rest], Acc) -> tokenise(Rest, [ $- | Acc]); +tokenise("AM"++Rest, Acc) -> tokenise(Rest, [am | Acc]); +tokenise("PM"++Rest, Acc) -> tokenise(Rest, [pm | Acc]); + +%% Postel's Law +%% +%% be conservative in what you do, +%% be liberal in what you accept from others. +%% +%% See RFC 793 Section 2.10 http://tools.ietf.org/html/rfc793 +%% +%% Mebbies folk want to include Saturday etc in a date, nae borra +tokenise("MONDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("MON"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("TUESDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("TUES"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("TUE"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("WEDNESDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("WEDS"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("WED"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("THURSDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("THURS"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("THUR"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("THU"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("FRIDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("FRI"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("SATURDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("SAT"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("SUNDAY"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("SUN"++Rest, Acc) -> tokenise(Rest, Acc); + +%% Hmm Excel reports GMT in times so nuke that too +tokenise("GMT"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("UTC"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("DST"++Rest, Acc) -> tokenise(Rest, Acc); % daylight saving time + +tokenise([$, | Rest], Acc) -> tokenise(Rest, Acc); +tokenise([32 | Rest], Acc) -> tokenise(Rest, Acc); % Spaces +tokenise("TH"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("ND"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("ST"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("OF"++Rest, Acc) -> tokenise(Rest, Acc); + +tokenise([Else | Rest], Acc) -> + tokenise(Rest, [{bad_token, Else} | Acc]). + +hour(Hour, []) -> Hour; +hour(Hour, [am]) -> Hour; +hour(Hour, [pm]) -> Hour+12. + +-spec format(string(),datetime(),list()) -> string(). +%% Finished, return +format([], _Date, Acc) -> + lists:flatten(lists:reverse(Acc)); + +%% Escape backslashes +format([$\\,H|T], Dt, Acc) -> + format(T,Dt,[H|Acc]); + +%% Year Formats +format([$Y|T], {{Y,_,_},_}=Dt, Acc) -> + format(T, Dt, [itol(Y)|Acc]); +format([$y|T], {{Y,_,_},_}=Dt, Acc) -> + [_, _, Y3, Y4] = itol(Y), + format(T, Dt, [[Y3,Y4]|Acc]); +format([$L|T], {{Y,_,_},_}=Dt, Acc) -> + format(T, Dt, [itol(is_leap(Y))|Acc]); +format([$o|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [itol(iso_year(Date))|Acc]); + +%% Month Formats +format([$n|T], {{_,M,_},_}=Dt, Acc) -> + format(T, Dt, [itol(M)|Acc]); +format([$m|T], {{_,M,_},_}=Dt, Acc) -> + format(T, Dt, [pad2(M)|Acc]); +format([$M|T], {{_,M,_},_}=Dt, Acc) -> + format(T, Dt, [smonth(M)|Acc]); +format([$F|T], {{_,M,_},_}=Dt, Acc) -> + format(T, Dt, [month(M)|Acc]); +format([$t|T], {{Y,M,_},_}=Dt, Acc) -> + format(T, Dt, [itol(calendar:last_day_of_the_month(Y,M))|Acc]); + +%% Week Formats +format([$W|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [pad2(iso_week(Date))|Acc]); + +%% Day Formats +format([$j|T], {{_,_,D},_}=Dt, Acc) -> + format(T, Dt, [itol(D)|Acc]); +format([$S|T], {{_,_,D},_}=Dt, Acc) -> + format(T, Dt,[suffix(D)| Acc]); +format([$d|T], {{_,_,D},_}=Dt, Acc) -> + format(T, Dt, [pad2(D)|Acc]); +format([$D|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [sdayd(Date)|Acc]); +format([$l|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [day(calendar:day_of_the_week(Date))|Acc]); +format([$N|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [itol(calendar:day_of_the_week(Date))|Acc]); +format([$w|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [itol(to_w(calendar:day_of_the_week(Date)))|Acc]); +format([$z|T], {Date,_}=Dt, Acc) -> + format(T, Dt, [itol(days_in_year(Date))|Acc]); + +%% Time Formats +format([$a|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, ["pm"|Acc]); +format([$a|T], Dt, Acc) -> + format(T, Dt, ["am"|Acc]); +format([$A|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, ["PM"|Acc]); +format([$A|T], Dt, Acc) -> + format(T, Dt, ["AM"|Acc]); +format([$g|T], {_,{H,_,_}}=Dt, Acc) when H == 12; H == 0 -> + format(T, Dt, ["12"|Acc]); +format([$g|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, [itol(H-12)|Acc]); +format([$g|T], {_,{H,_,_}}=Dt, Acc) -> + format(T, Dt, [itol(H)|Acc]); +format([$G|T], {_,{H,_,_}}=Dt, Acc) -> + format(T, Dt, [itol(H)|Acc]); +format([$h|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, [pad2(H-12)|Acc]); +format([$h|T], {_,{H,_,_}}=Dt, Acc) -> + format(T, Dt, [pad2(H)|Acc]); +format([$H|T], {_,{H,_,_}}=Dt, Acc) -> + format(T, Dt, [pad2(H)|Acc]); +format([$i|T], {_,{_,M,_}}=Dt, Acc) -> + format(T, Dt, [pad2(M)|Acc]); +format([$s|T], {_,{_,_,S}}=Dt, Acc) -> + format(T, Dt, [pad2(S)|Acc]); + +%% Whole Dates +format([$c|T], {{Y,M,D},{H,Min,S}}=Dt, Acc) -> + Format = "~4.10.0B-~2.10.0B-~2.10.0B" + ++" ~2.10.0B:~2.10.0B:~2.10.0B", + Date = io_lib:format(Format, [Y, M, D, H, Min, S]), + format(T, Dt, [Date|Acc]); +format([$r|T], {{Y,M,D},{H,Min,S}}=Dt, Acc) -> + Format = "~s, ~p ~s ~p ~2.10.0B:~2.10.0B:~2.10.0B", + Args = [sdayd({Y,M,D}), D, smonth(M), Y, H, Min, S], + format(T, Dt, [io_lib:format(Format, Args)|Acc]); +format([$U|T], Dt, Acc) -> + Epoch = {{1970,1,1},{0,0,0}}, + Time = calendar:datetime_to_gregorian_seconds(Dt) - + calendar:datetime_to_gregorian_seconds(Epoch), + format(T, Dt, [itol(Time)|Acc]); + +%% Unrecognised, print as is +format([H|T], Date, Acc) -> + format(T, Date, [H|Acc]). + + +%% @doc days in year +-spec days_in_year(date()) -> integer(). +days_in_year({Y,_,_}=Date) -> + calendar:date_to_gregorian_days(Date) - + calendar:date_to_gregorian_days({Y,1,1}). + +%% @doc is a leap year +-spec is_leap(year()) -> 1|0. +is_leap(Y) -> + case calendar:is_leap_year(Y) of + true -> 1; + false -> 0 + end. + +%% @doc Made up numeric day of the week +%% (0 Sunday -> 6 Saturday) +-spec to_w(daynum()) -> integer(). +to_w(7) -> 0; +to_w(X) -> X. + +-spec suffix(day()) -> string(). +%% @doc English ordinal suffix for the day of the +%% month, 2 characters +suffix(1) -> "st"; +suffix(2) -> "nd"; +suffix(3) -> "rd"; +suffix(_) -> "th". + +-spec sdayd(date()) -> string(). +%% @doc A textual representation of a day, three letters +sdayd({Y,M,D}) -> + sday(calendar:day_of_the_week({Y,M,D})). + +-spec sday(daynum()) -> string(). +%% @doc A textual representation of a day, three letters +sday(1) -> "Mon"; +sday(2) -> "Tue"; +sday(3) -> "Wed"; +sday(4) -> "Thu"; +sday(5) -> "Fri"; +sday(6) -> "Sat"; +sday(7) -> "Sun". + +-spec day(daynum()) -> string(). +%% @doc A full textual representation of a day +day(1) -> "Monday"; +day(2) -> "Tuesday"; +day(3) -> "Wednesday"; +day(4) -> "Thursday"; +day(5) -> "Friday"; +day(6) -> "Saturday"; +day(7) -> "Sunday". + +-spec smonth(month()) -> string(). +%% @doc A short textual representation of a +%% month, three letters +smonth(1) -> "Jan"; +smonth(2) -> "Feb"; +smonth(3) -> "Mar"; +smonth(4) -> "Apr"; +smonth(5) -> "May"; +smonth(6) -> "Jun"; +smonth(7) -> "Jul"; +smonth(8) -> "Aug"; +smonth(9) -> "Sep"; +smonth(10) -> "Oct"; +smonth(11) -> "Nov"; +smonth(12) -> "Dec". + +-spec month(month()) -> string(). +%% @doc A full textual representation of a month +month(1) -> "January"; +month(2) -> "February"; +month(3) -> "March"; +month(4) -> "April"; +month(5) -> "May"; +month(6) -> "June"; +month(7) -> "July"; +month(8) -> "August"; +month(9) -> "September"; +month(10) -> "October"; +month(11) -> "November"; +month(12) -> "December". + +-spec iso_week(date()) -> integer(). +%% @doc The week of the years as defined in ISO 8601 +%% http://en.wikipedia.org/wiki/ISO_week_date +iso_week(Date) -> + Week = iso_week_one(iso_year(Date)), + Days = calendar:date_to_gregorian_days(Date) - + calendar:date_to_gregorian_days(Week), + trunc((Days / 7) + 1). + +-spec iso_year(date()) -> integer(). +%% @doc The year number as defined in ISO 8601 +%% http://en.wikipedia.org/wiki/ISO_week_date +iso_year({Y, _M, _D}=Dt) -> + case Dt >= {Y, 12, 29} of + true -> + case Dt < iso_week_one(Y+1) of + true -> Y; + false -> Y+1 + end; + false -> + case Dt < iso_week_one(Y) of + true -> Y-1; + false -> Y + end + end. + +-spec iso_week_one(year()) -> date(). +%% @doc The date of the the first day of the first week +%% in the ISO calendar +iso_week_one(Y) -> + Day1 = calendar:day_of_the_week({Y,1,4}), + Days = calendar:date_to_gregorian_days({Y,1,4}) + (1-Day1), + calendar:gregorian_days_to_date(Days). + +-spec itol(integer()) -> list(). +%% @doc short hand +itol(X) -> + integer_to_list(X). + +-spec pad2(integer()) -> list(). +%% @doc int padded with 0 to make sure its 2 chars +pad2(X) when is_integer(X) -> + io_lib:format("~2.10.0B",[X]); +pad2(X) when is_float(X) -> + io_lib:format("~2.10.0B",[trunc(X)]). + +ltoi(X) -> + list_to_integer(X). + +%% +%% TEST FUNCTIONS +%% +%% c(dh_date,[{d,'TEST'}]). +%-define(NOTEST, 1). + +-include_lib("eunit/include/eunit.hrl"). + +-define(DATE, {{2001,3,10},{17,16,17}}). +-define(ISO, "o \\WW"). + +basic_format_test_() -> + [ + ?_assertEqual(format("F j, Y, g:i a",?DATE), "March 10, 2001, 5:16 pm"), + ?_assertEqual(format("m.d.y",?DATE), "03.10.01"), + ?_assertEqual(format("j, n, Y",?DATE), "10, 3, 2001"), + ?_assertEqual(format("Ymd",?DATE), "20010310"), + ?_assertEqual(format("H:i:s",?DATE), "17:16:17"), + ?_assertEqual(format("z",?DATE), "68"), + ?_assertEqual(format("D M j G:i:s Y",?DATE), "Sat Mar 10 17:16:17 2001"), + + ?_assertEqual(format("h-i-s, j-m-y, it is w Day",?DATE), + "05-16-17, 10-03-01, 1631 1617 6 Satpm01"), + ?_assertEqual(format("\\i\\t \\i\\s \\t\\h\\e\\ jS \\d\\a\\y.",?DATE), + "it is the 10th day."), + ?_assertEqual(format("H:m:s \\m \\i\\s \\m\\o\\n\\t\\h",?DATE), + "17:03:17 m is month") + ]. + +basic_parse_test_() -> + [ + ?_assertEqual({{2008,8,22}, {17,16,17}}, + parse("22nd of August 2008", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22-Aug-2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,12}}, + parse("22-Aug-2008 6:35:12 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22/Aug/2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22/August/2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22 August 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22 Aug 2008 6:35AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22 Aug 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("22 Aug 2008 6:35", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,35,0}}, + parse("22 Aug 2008 6:35 PM", ?DATE)), + ?_assertEqual({{2001,3,10}, {11,15,0}}, + parse("11:15", ?DATE)), + ?_assertEqual({{2001,3,10}, {1,15,0}}, + parse("1:15", ?DATE)), + ?_assertEqual({{2001,3,10}, {1,15,0}}, + parse("1:15 am", ?DATE)), + ?_assertEqual({{2001,3,10}, {3,45,39}}, + parse("3:45:39", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("23/4/1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("23/april/1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("23/apr/1963", ?DATE)), + ?_assertEqual({error, bad_date}, + parse("23/ap/195", ?DATE)), + ?_assertEqual({{2001,3,10}, {6,45,0}}, + parse("6:45 am", ?DATE)), + ?_assertEqual({{2001,3,10}, {18,45,0}}, + parse("6:45 PM", ?DATE)), + ?_assertEqual({{2001,3,10}, {18,45,0}}, + parse("6:45 PM ", ?DATE)) + ]. + +parse_with_days_test_() -> + [ + ?_assertEqual({{2008,8,22}, {17,16,17}}, + parse("Sat 22nd of August 2008", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("Sat, 22-Aug-2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,12}}, + parse("Sunday 22-Aug-2008 6:35:12 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("Sun 22/Aug/2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("THURSDAY, 22/August/2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("THU 22 August 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("FRi 22 Aug 2008 6:35AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("Wednesday 22 Aug 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,35,0}}, + parse("Monday 22 Aug 2008 6:35", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,35,0}}, + parse("Mon, 22 Aug 2008 6:35 PM", ?DATE)) + ]. + +parse_with_TZ_test_() -> + [ + ?_assertEqual({{2008,8,22}, {17,16,17}}, + parse("Sat 22nd of August 2008 GMT", ?DATE)), + ?_assertEqual({{2008,8,22}, {17,16,17}}, + parse("Sat 22nd of August 2008 UTC", ?DATE)), + ?_assertEqual({{2008,8,22}, {17,16,17}}, + parse("Sat 22nd of August 2008 DST", ?DATE)) + ]. + +iso_test_() -> + [ + ?_assertEqual("2004 W53",format(?ISO,{{2005,1,1}, {1,1,1}})), + ?_assertEqual("2004 W53",format(?ISO,{{2005,1,2}, {1,1,1}})), + ?_assertEqual("2005 W52",format(?ISO,{{2005,12,31},{1,1,1}})), + ?_assertEqual("2007 W01",format(?ISO,{{2007,1,1}, {1,1,1}})), + ?_assertEqual("2007 W52",format(?ISO,{{2007,12,30},{1,1,1}})), + ?_assertEqual("2008 W01",format(?ISO,{{2007,12,31},{1,1,1}})), + ?_assertEqual("2008 W01",format(?ISO,{{2008,1,1}, {1,1,1}})), + ?_assertEqual("2009 W01",format(?ISO,{{2008,12,29},{1,1,1}})), + ?_assertEqual("2009 W01",format(?ISO,{{2008,12,31},{1,1,1}})), + ?_assertEqual("2009 W01",format(?ISO,{{2009,1,1}, {1,1,1}})), + ?_assertEqual("2009 W53",format(?ISO,{{2009,12,31},{1,1,1}})), + ?_assertEqual("2009 W53",format(?ISO,{{2010,1,3}, {1,1,1}})) + ]. From 6d969cd55e9188635cbeb083378ba288a405a2ee Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 17 Oct 2011 16:09:23 -0500 Subject: [PATCH 005/240] convert date parsing library from tagged return types to exceptions Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 1eda795..afe83db 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -56,12 +56,12 @@ format(Format, {_,_,_}=Now) -> format(Format, Date) -> format(Format, Date, []). --spec parse(string()) -> datetime() | {error, bad_date}. +-spec parse(string()) -> datetime(). %% @doc parses the datetime from a string parse(Date) -> do_parse(Date, calendar:universal_time(),[]). --spec parse(string(),datetime() | now()) -> datetime() | {error, bad_date}. +-spec parse(string(),datetime() | now()) -> datetime(). %% @doc parses the datetime from a string parse(Date, {_,_,_}=Now) -> do_parse(Date, calendar:now_to_datetime(Now), []); @@ -71,16 +71,16 @@ parse(Date, Now) -> do_parse(Date, Now, Opts) -> case parse(tokenise(string:to_upper(Date), []), Now, Opts) of {error, bad_date} -> - {error, bad_date}; + erlang:throw({?MODULE, {bad_date, Date}}); {D1, T1} = {{Y, M, D}, {H, M1, S}} when is_number(Y), is_number(M), is_number(D), is_number(H), is_number(M1), is_number(S) -> case calendar:valid_date(D1) of true -> {D1, T1}; - false -> {error, bad_date} + false -> erlang:throw({?MODULE, {bad_date, Date}}) end; - _ -> {error, bad_date} + _ -> erlang:throw({?MODULE, {bad_date, Date}}) end. -spec nparse(string()) -> now(). @@ -519,7 +519,7 @@ basic_parse_test_() -> parse("23/april/1963", ?DATE)), ?_assertEqual({{1963,4,23}, {17,16,17}}, parse("23/apr/1963", ?DATE)), - ?_assertEqual({error, bad_date}, + ?_assertThrow({?MODULE, {bad_date, "23/ap/195"}}, parse("23/ap/195", ?DATE)), ?_assertEqual({{2001,3,10}, {6,45,0}}, parse("6:45 am", ?DATE)), From 6d17415cdd3ae1e3ff74f84adbfc2f3a92842dc0 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 17 Oct 2011 16:08:13 -0500 Subject: [PATCH 006/240] support US style date parsing using the same defaults from php as the original Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 84 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index afe83db..6662dd6 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -3,10 +3,17 @@ %% %% Licensed under the MIT license %% -%% This module formats erlang dates in the form -%% {{Year, Month, Day}, {Hour, Minute, Second}} -%% to printable strings, using (almost) equivalent -%% formatting rules as http://uk.php.net/date +%% This module formats erlang dates in the form {{Year, Month, Day}, +%% {Hour, Minute, Second}} to printable strings, using (almost) +%% equivalent formatting rules as http://uk.php.net/date, US vs +%% European dates are disambiguated in the same way as +%% http://uk.php.net/manual/en/function.strtotime.php That is, Dates +%% in the m/d/y or d-m-y formats are disambiguated by looking at the +%% separator between the various components: if the separator is a +%% slash (/), then the American m/d/y is assumed; whereas if the +%% separator is a dash (-) or a dot (.), then the European d-m-y +%% format is assumed. To avoid potential ambiguity, it's best to use +%% ISO 8601 (YYYY-MM-DD) dates. %% %% erlang has no concept of timezone so the following %% formats are not implemented: B e I O P T Z @@ -24,7 +31,8 @@ %% defines make sense -define( is_num(X), (X >= $0 andalso X =< $9) ). -define( is_meridian(X), (X==[] orelse X==[am] orelse X==[pm]) ). --define( is_sep(X), (X==$- orelse X==$/) ). +-define( is_us_sep(X), ( X==$/) ). +-define( is_world_sep(X), ( X==$-) ). -define(GREGORIAN_SECONDS_1970, 62167219200). @@ -105,16 +113,40 @@ parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> %% Dates 23/april/1963 parse([Day,Month,Year], {_Date, Time}, _Opts) -> {{Year, Month, Day}, Time}; -parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_sep(X) -> +parse([Year,X,Month,X,Day], {_Date, Time}, _Opts) + when (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, Time}; +parse([Month,X,Day,X,Year], {_Date, Time}, _Opts) when ?is_us_sep(X) -> + {{Year, Month, Day}, Time}; +parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_world_sep(X) -> {{Year, Month, Day}, Time}; %% Date/Times 22 Aug 2008 6:35 PM -parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso ?is_sep(X) -> +parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso + (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; -parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_sep(X) -> +parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso ?is_world_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; +parse([Month,X,Day,X,Year,Hour,$:,Min | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso ?is_us_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; + +parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso + (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; +parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_us_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; +parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_world_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; + parse([Day,Month,Year,Hour,$:,Min | PAM], _Now, _Opts) when ?is_meridian(PAM) -> @@ -492,9 +524,7 @@ basic_parse_test_() -> ?_assertEqual({{2008,8,22}, {6,35,12}}, parse("22-Aug-2008 6:35:12 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22/Aug/2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22/August/2008 6:35 AM", ?DATE)), + parse("August/22/2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22 August 2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, @@ -514,11 +544,29 @@ basic_parse_test_() -> ?_assertEqual({{2001,3,10}, {3,45,39}}, parse("3:45:39", ?DATE)), ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23/4/1963", ?DATE)), + parse("23-4-1963", ?DATE)), ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23/april/1963", ?DATE)), + parse("23-april-1963", ?DATE)), ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23/apr/1963", ?DATE)), + parse("23-apr-1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("4/23/1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("april/23/1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("apr/23/1963", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963/4/23", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963/april/23", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963/apr/23", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963-4-23", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963-4-23", ?DATE)), + ?_assertEqual({{1963,4,23}, {17,16,17}}, + parse("1963-apr-23", ?DATE)), ?_assertThrow({?MODULE, {bad_date, "23/ap/195"}}, parse("23/ap/195", ?DATE)), ?_assertEqual({{2001,3,10}, {6,45,0}}, @@ -538,9 +586,9 @@ parse_with_days_test_() -> ?_assertEqual({{2008,8,22}, {6,35,12}}, parse("Sunday 22-Aug-2008 6:35:12 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("Sun 22/Aug/2008 6:35 AM", ?DATE)), + parse("Sun 22-Aug-2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("THURSDAY, 22/August/2008 6:35 AM", ?DATE)), + parse("THURSDAY, 22-August-2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("THU 22 August 2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, From 493388125432a5c4b4f8c7783d489f317200c078 Mon Sep 17 00:00:00 2001 From: Yurii Rashkovskii Date: Sat, 19 Nov 2011 12:25:45 -0800 Subject: [PATCH 007/240] Adds ec_talk to erlware_commons app modules --- ebin/erlware_commons.app | 1 + 1 file changed, 1 insertion(+) diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index ff59dde..6031e94 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -3,6 +3,7 @@ [{description, "Additional standard library for Erlang"}, {vsn, "0.6.0"}, {modules, [ + ec_talk, ec_lists, ec_plists, ec_file, From de3f0530d614b6c321d79154b06f56ae3c1e4047 Mon Sep 17 00:00:00 2001 From: Gordon Guthrie Date: Mon, 19 Dec 2011 11:03:27 +0000 Subject: [PATCH 008/240] Fix for typo. Pushed up stream from choptastic's bug fix to dh_date https://github.com/daleharvey/dh_date/pull/4 --- src/ec_date.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 6662dd6..7aeac3f 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -173,7 +173,7 @@ tokenise([N1 | Rest], Acc) tokenise("JANUARY"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); tokenise("JAN"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); -tokenise("FEBUARY"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); +tokenise("FEBRUARY"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); tokenise("FEB"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); tokenise("MARCH"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); tokenise("MAR"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); From 8353035a1e70e8f5011233573c59080cff188256 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 27 Oct 2011 09:56:22 -0500 Subject: [PATCH 009/240] whitespace and comment refactoring This patch replaces tabs with spaces and converts the '%' inline comments (which according to the emacs mode are actually end of line comments) to the mode acceptable '%%' inline comments. Signed-off-by: Jordan Wilberding --- src/ec_assoc_list.erl | 52 +++++++-------- src/ec_dict.erl | 58 ++++++++-------- src/ec_dictionary.erl | 28 ++++---- src/ec_file.erl | 10 +-- src/ec_orddict.erl | 54 +++++++-------- src/ec_plists.erl | 12 ++-- src/ec_rbdict.erl | 150 +++++++++++++++++++++--------------------- 7 files changed, 182 insertions(+), 182 deletions(-) diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl index 1fdb2c4..0ea9d68 100644 --- a/src/ec_assoc_list.erl +++ b/src/ec_assoc_list.erl @@ -13,16 +13,16 @@ %% API -export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). -export_type([dictionary/2]). @@ -30,7 +30,7 @@ %%% Types %%%=================================================================== -opaque dictionary(K, V) :: {ec_assoc_list, - [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. + [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. %%%=================================================================== %%% API @@ -48,26 +48,26 @@ has_key(Key, {ec_assoc_list, Data}) -> ec_dictionary:value(V). get(Key, {ec_assoc_list, Data}) -> case lists:keyfind(Key, 1, Data) of - {Key, Value} -> - Value; - false -> - throw(not_found) + {Key, Value} -> + Value; + false -> + throw(not_found) end. -spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::dictionary(K, V)) -> - ec_dictionary:value(V). + ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). get(Key, Default, {ec_assoc_list, Data}) -> case lists:keyfind(Key, 1, Data) of - {Key, Value} -> - Value; - false -> - Default + {Key, Value} -> + Value; + false -> + Default end. -spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> + Object::dictionary(K, V)) -> dictionary(K, V). add(Key, Value, {ec_assoc_list, _Data}=Dict) -> {ec_assoc_list, Rest} = remove(Key,Dict), @@ -87,7 +87,7 @@ size({ec_assoc_list, Data}) -> length(Data). -spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. + ec_dictionary:value(V)}]. to_list({ec_assoc_list, Data}) -> Data. @@ -99,5 +99,5 @@ from_list(List) when is_list(List) -> -spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. keys({ec_assoc_list, Data}) -> lists:map(fun({Key, _Value}) -> - Key - end, Data). + Key + end, Data). diff --git a/src/ec_dict.erl b/src/ec_dict.erl index b760e92..2eb61e7 100644 --- a/src/ec_dict.erl +++ b/src/ec_dict.erl @@ -15,16 +15,16 @@ %% API -export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). -export_type([dictionary/2]). @@ -49,26 +49,26 @@ has_key(Key, Data) -> ec_dictionary:value(V). get(Key, Data) -> case dict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - throw(not_found) + {ok, Value} -> + Value; + error -> + throw(not_found) end. -spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::dictionary(K, V)) -> - ec_dictionary:value(V). + ec_dictionary:value(V), + Object::dictionary(K, V)) -> + ec_dictionary:value(V). get(Key, Default, Data) -> case dict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - Default + {ok, Value} -> + Value; + error -> + Default end. -spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> + Object::dictionary(K, V)) -> dictionary(K, V). add(Key, Value, Data) -> dict:store(Key, Value, Data). @@ -81,19 +81,19 @@ remove(Key, Data) -> -spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). has_value(Value, Data) -> dict:fold(fun(_, NValue, _) when NValue == Value -> - true; - (_, _, Acc) -> - Acc - end, - false, - Data). + true; + (_, _, Acc) -> + Acc + end, + false, + Data). -spec size(Object::dictionary(_K, _V)) -> integer(). size(Data) -> dict:size(Data). -spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. + ec_dictionary:value(V)}]. to_list(Data) -> dict:to_list(Data). diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl index 0e0e11b..bc2fc91 100644 --- a/src/ec_dictionary.erl +++ b/src/ec_dictionary.erl @@ -15,28 +15,28 @@ %% API -export([new/1, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/2, - keys/1]). + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/2, + keys/1]). -export_type([dictionary/2, - key/1, - value/1]). + key/1, + value/1]). %%%=================================================================== %%% Types %%%=================================================================== -record(dict_t, - {callback, - data}). + {callback, + data}). -opaque dictionary(_K, _V) :: #dict_t{}. -type key(T) :: T. diff --git a/src/ec_file.erl b/src/ec_file.erl index 15f9f54..f4d9d88 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -123,10 +123,10 @@ mkdtemp() -> %% @doc Makes a directory including parent dirs if they are missing. -spec mkdir_path(path()) -> ok. mkdir_path(Path) -> - % We are exploiting a feature of ensuredir that that creates all - % directories up to the last element in the filename, then ignores - % that last element. This way we ensure that the dir is created - % and not have any worries about path names + %% We are exploiting a feature of ensuredir that that creates all + %% directories up to the last element in the filename, then ignores + %% that last element. This way we ensure that the dir is created + %% and not have any worries about path names DirName = filename:join([filename:absname(Path), "tmp"]), try ok = filelib:ensure_dir(DirName) @@ -343,7 +343,7 @@ setup_base_and_target() -> {BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}. find_test() -> - % Create a directory in /tmp for the test. Clean everything afterwards + %% Create a directory in /tmp for the test. Clean everything afterwards {setup, fun setup_base_and_target/0, diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl index 71f3d23..51a7d40 100644 --- a/src/ec_orddict.erl +++ b/src/ec_orddict.erl @@ -15,16 +15,16 @@ %% API -export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). -export_type([dictionary/2]). @@ -49,26 +49,26 @@ has_key(Key, Data) -> ec_dictionary:value(V). get(Key, Data) -> case orddict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - throw(not_found) + {ok, Value} -> + Value; + error -> + throw(not_found) end. -spec get(ec_dictionary:key(K), - Default::ec_dictionary:value(V), - Object::dictionary(K, V)) -> + Default::ec_dictionary:value(V), + Object::dictionary(K, V)) -> ec_dictionary:value(V). get(Key, Default, Data) -> case orddict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - Default + {ok, Value} -> + Value; + error -> + Default end. -spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> + Object::dictionary(K, V)) -> dictionary(K, V). add(Key, Value, Data) -> orddict:store(Key, Value, Data). @@ -81,12 +81,12 @@ remove(Key, Data) -> -spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). has_value(Value, Data) -> orddict:fold(fun(_, NValue, _) when NValue == Value -> - true; - (_, _, Acc) -> - Acc - end, - false, - Data). + true; + (_, _, Acc) -> + Acc + end, + false, + Data). -spec size(Object::dictionary(_K, _V)) -> integer(). size(Data) -> diff --git a/src/ec_plists.erl b/src/ec_plists.erl index b7b9260..a90bc38 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -111,9 +111,9 @@ map_gather([{Pid, _E} | Rest]) -> receive {Pid, {value, Ret}} -> [Ret|map_gather(Rest)]; - % timeouts fall here too. Should timeouts be a return value - % or an exception? I lean toward return value, but the code - % is easier with the exception. Thoughts? + %% timeouts fall here too. Should timeouts be a return value + %% or an exception? I lean toward return value, but the code + %% is easier with the exception. Thoughts? {Pid, Exception} -> killall(Rest), throw(Exception) @@ -153,9 +153,9 @@ do_f(Parent, F, E) -> Parent ! {self(), {value, Result}} catch _Class:Exception -> - % Losing class info here, but since throw does not accept - % that arg anyhow and forces a class of throw it does not - % matter. + %% Losing class info here, but since throw does not accept + %% that arg anyhow and forces a class of throw it does not + %% matter. Parent ! {self(), Exception} end. diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl index 0e962ec..bb89674 100644 --- a/src/ec_rbdict.erl +++ b/src/ec_rbdict.erl @@ -60,8 +60,8 @@ %% Standard interface. -export([add/3, from_list/1, get/2, get/3, has_key/2, - has_value/2, new/0, remove/2, size/1, to_list/1, - keys/1]). + has_value/2, new/0, remove/2, size/1, to_list/1, + keys/1]). -export_type([dictionary/2]). @@ -70,10 +70,10 @@ %%%=================================================================== -opaque dictionary(K, V) :: empty | {color(), - dictionary(K, V), - ec_dictionary:key(K), - ec_dictionary:value(V), - dictionary(K, V)}. + dictionary(K, V), + ec_dictionary:key(K), + ec_dictionary:value(V), + dictionary(K, V)}. -type color() :: r | b. @@ -105,8 +105,8 @@ get(_, {_, _, _, Val, _}) -> Val. -spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - dictionary(K, V)) -> ec_dictionary:value(V). + ec_dictionary:value(V), + dictionary(K, V)) -> ec_dictionary:value(V). get(_, Default, empty) -> Default; get(K, Default, {_, Left, K1, _, _}) when K < K1 -> @@ -117,7 +117,7 @@ get(_, _, {_, _, _, Val, _}) -> Val. -spec add(ec_dicitonary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> dictionary(K, V). + dictionary(K, V)) -> dictionary(K, V). add(Key, Value, Dict) -> {_, L, K1, V1, R} = add1(Key, Value, Dict), {b, L, K1, V1, R}. @@ -129,9 +129,9 @@ remove(Key, Dictionary) -> -spec has_value(ec_dictionary:value(V), dictionary(_K, V)) -> boolean(). has_value(Value, Dict) -> fold(fun (_, NValue, _) when NValue == Value -> true; - (_, _, Acc) -> Acc - end, - false, Dict). + (_, _, Acc) -> Acc + end, + false, Dict). -spec size(dictionary(_K, _V)) -> integer(). size(T) -> @@ -146,9 +146,9 @@ to_list(T) -> dictionary(K, V). from_list(L) -> lists:foldl(fun ({K, V}, D) -> - add(K, V, D) - end, new(), - L). + add(K, V, D) + end, new(), + L). -spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. keys(Dict) -> @@ -171,59 +171,59 @@ erase_aux(_, empty) -> {empty, false}; erase_aux(K, {b, A, Xk, Xv, B}) -> if K < Xk -> - {A1, Dec} = erase_aux(K, A), - if Dec -> - unbalright(b, A1, Xk, Xv, B); - true -> - {{b, A1, Xk, Xv, B}, false} - end; + {A1, Dec} = erase_aux(K, A), + if Dec -> + unbalright(b, A1, Xk, Xv, B); + true -> + {{b, A1, Xk, Xv, B}, false} + end; K > Xk -> - {B1, Dec} = erase_aux(K, B), - if Dec -> - unballeft(b, A, Xk, Xv, B1); - true -> - {{b, A, Xk, Xv, B1}, false} - end; + {B1, Dec} = erase_aux(K, B), + if Dec -> + unballeft(b, A, Xk, Xv, B1); + true -> + {{b, A, Xk, Xv, B1}, false} + end; true -> - case B of - empty -> - blackify(A); - _ -> - {B1, {Mk, Mv}, Dec} = erase_min(B), - if Dec -> - unballeft(b, A, Mk, Mv, B1); - true -> - {{b, A, Mk, Mv, B1}, false} - end - end + case B of + empty -> + blackify(A); + _ -> + {B1, {Mk, Mv}, Dec} = erase_min(B), + if Dec -> + unballeft(b, A, Mk, Mv, B1); + true -> + {{b, A, Mk, Mv, B1}, false} + end + end end; erase_aux(K, {r, A, Xk, Xv, B}) -> if K < Xk -> - {A1, Dec} = erase_aux(K, A), - if Dec -> - unbalright(r, A1, Xk, Xv, B); - true -> - {{r, A1, Xk, Xv, B}, false} - end; + {A1, Dec} = erase_aux(K, A), + if Dec -> + unbalright(r, A1, Xk, Xv, B); + true -> + {{r, A1, Xk, Xv, B}, false} + end; K > Xk -> - {B1, Dec} = erase_aux(K, B), - if Dec -> - unballeft(r, A, Xk, Xv, B1); - true -> - {{r, A, Xk, Xv, B1}, false} - end; + {B1, Dec} = erase_aux(K, B), + if Dec -> + unballeft(r, A, Xk, Xv, B1); + true -> + {{r, A, Xk, Xv, B1}, false} + end; true -> - case B of - empty -> - {A, false}; - _ -> - {B1, {Mk, Mv}, Dec} = erase_min(B), - if Dec -> - unballeft(r, A, Mk, Mv, B1); - true -> - {{r, A, Mk, Mv, B1}, false} - end - end + case B of + empty -> + {A, false}; + _ -> + {B1, {Mk, Mv}, Dec} = erase_min(B), + if Dec -> + unballeft(r, A, Mk, Mv, B1); + true -> + {{r, A, Mk, Mv, B1}, false} + end + end end. -spec erase_min(dictionary(K, V)) -> @@ -239,15 +239,15 @@ erase_min({r, empty, Xk, Xv, A}) -> erase_min({b, A, Xk, Xv, B}) -> {A1, Min, Dec} = erase_min(A), if Dec -> - {T, Dec1} = unbalright(b, A1, Xk, Xv, B), - {T, Min, Dec1}; + {T, Dec1} = unbalright(b, A1, Xk, Xv, B), + {T, Min, Dec1}; true -> {{b, A1, Xk, Xv, B}, Min, false} end; erase_min({r, A, Xk, Xv, B}) -> {A1, Min, Dec} = erase_min(A), if Dec -> - {T, Dec1} = unbalright(r, A1, Xk, Xv, B), - {T, Min, Dec1}; + {T, Dec1} = unbalright(r, A1, Xk, Xv, B), + {T, Min, Dec1}; true -> {{r, A1, Xk, Xv, B}, Min, false} end. @@ -259,7 +259,7 @@ unballeft(r, {b, A, Xk, Xv, B}, Yk, Yv, C) -> unballeft(b, {b, A, Xk, Xv, B}, Yk, Yv, C) -> {lbalance(b, {r, A, Xk, Xv, B}, Yk, Yv, C), true}; unballeft(b, {r, A, Xk, Xv, {b, B, Yk, Yv, C}}, Zk, Zv, - D) -> + D) -> {{b, A, Xk, Xv, lbalance(b, {r, B, Yk, Yv, C}, Zk, Zv, D)}, false}. @@ -269,7 +269,7 @@ unbalright(r, A, Xk, Xv, {b, B, Yk, Yv, C}) -> unbalright(b, A, Xk, Xv, {b, B, Yk, Yv, C}) -> {rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), true}; unbalright(b, A, Xk, Xv, - {r, {b, B, Yk, Yv, C}, Zk, Zv, D}) -> + {r, {b, B, Yk, Yv, C}, Zk, Zv, D}) -> {{b, rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), Zk, Zv, D}, false}. @@ -295,25 +295,25 @@ to_list({_, A, Xk, Xv, B}, List) -> %% Balance a tree afer (possibly) adding a node to the left/right. -spec lbalance(color(), dictionary(K, V), - ec_dictinary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> + ec_dictinary:key(K), ec_dictionary:value(V), + dictionary(K, V)) -> dictionary(K, V). lbalance(b, {r, {r, A, Xk, Xv, B}, Yk, Yv, C}, Zk, Zv, - D) -> + D) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; lbalance(b, {r, A, Xk, Xv, {r, B, Yk, Yv, C}}, Zk, Zv, - D) -> + D) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; lbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. -spec rbalance(color(), dictionary(K, V), - ec_dictinary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> + ec_dictinary:key(K), ec_dictionary:value(V), + dictionary(K, V)) -> dictionary(K, V). rbalance(b, A, Xk, Xv, - {r, {r, B, Yk, Yv, C}, Zk, Zv, D}) -> + {r, {r, B, Yk, Yv, C}, Zk, Zv, D}) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; rbalance(b, A, Xk, Xv, - {r, B, Yk, Yv, {r, C, Zk, Zv, D}}) -> + {r, B, Yk, Yv, {r, C, Zk, Zv, D}}) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; rbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. From 6f2b3efc0cf4923d415c177b86c8f7305c67a887 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 20 Feb 2012 13:45:15 -0600 Subject: [PATCH 010/240] Minimal correct readme Signed-off-by: Jordan Wilberding --- README.md | 547 ++---------------------------------------------------- 1 file changed, 17 insertions(+), 530 deletions(-) diff --git a/README.md b/README.md index 5d0bc4f..5681fe6 100644 --- a/README.md +++ b/README.md @@ -1,534 +1,21 @@ -ERESYE - ERlang Expert SYstem Engine -======================================== +Erlware Commons +=============== Introduction ------------ -This article describe how to write a simple Artificial Intelligence -application with Erlang, by using a *rule production system*. - -To reach this objective, we will exploit the **ERESYE** tool, an -Erlang Inference Engine that allows rule-based systems to be written -directly in Erlang. - -As it is widely known, a rule-based system is composed by a -**knowledge base**, which stores a set of *facts* representing the -'universe of discourse' of a given application, and a set of -**production rules**, which are used to infer knowledge and/or reason -about the knowledge. A rule is activated when one or more facts match -the template(s) given in the rule declaration: in such a case, the -body of the rule contains a code that is thus executed - -In ERESYE, *facts* are expressed by means of Erlang tuples or records, -while rules are written using standard Erlang function clauses, whose -declaration reports, in the clause head, the facts or fact templates -that have to be matched for the rule to be activated and executed. - -For more information about ERESYE please refer to the paper docs directory. - -For more information about rule-based inference engines and expert -systems, you can refer to the book: *S. Russell and -P. Norvig. **Artificial Intelligence: A Modern Approach/2E.** Prentice -Hall, 2003.* - -To write an AI application with ERESYE the following steps have to be -performed: - -1. Indentify your universe of discourse and determine the facts that - have to be used to represent such a world; - -2. Indentify the rules that you need and write them by using, e.g. - first-order-logic predicates or even natural language; - -3. Implement the system by writing your rules as Erlang function - clauses, according to the modality required by ERESYE. - - -The Application: the Domain of Relatives ----------------------------------------- - -We will design a system able to derive new knowledge using some -inference rules and starting from a small set; as a sample -application, we chose the domain of relatives: we will start from some -base concepts, such as *parent*, *male* and *female*, and then, by -means of a proper set of rules, we will derive the concepts of -*mother*, *father*, *sister*, *brother*, *grandmother* and -*grandfather*. - -According to the list above, we will first derive the facts that will be -used to represent our concepts. Given the set of relationships above, they -will be represented by means of the following facts: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ConceptFact / Erlang tuple
1X is male{male, X}
2X is female{female, X}
3X is Y's parent{parent, X, Y}
4X is Y's mother{mother, X, Y}
5X is Y's father{father, X, Y}
6X is Y's sister{sister, X, Y}
7X is Y's brother{brother, X, Y}
8X is Y's grandmother{grandmother, X, Y}
9X is Y's grandfather{grandfather, X, Y}
- -Concepts 1, 2 and 3 will be used as a base to derive the other ones. - -Deriving new concepts by means of rules ---------------------------------------- - -#### Concept: mother - -The rule to derive the concept of mother is quite -straightforward: - - if X is female and X is Y's parent then X is Y's mother. - -From the point of view of ERESYE, since knowledge is stored in the -*knowledge base* of the engine, the rule above is translated into the -following one: *if the facts {female, X} and {parent, X, Y} are -*asserted* in the knowledge base, then we assert the fact {mother, X, -Y}. - -The rule *mother* can be thus written as follows: - - %% - %% if (X is female) and (X is Y's parent) then (X is Y's mother) - %% - mother (Engine, {female, X}, {parent, X, Y}) -> - eresye:assert (Engine, {mother, X, Y}). - - -#### Concept: father - -This concept can be easily derived by means of the following rule: - - %% - %% if (X is male) and (X is Y's parent) then (X is Y's father) - %% - father (Engine, {male, X}, {parent, X, Y}) -> - eresye:assert (Engine, {father, X, Y}). - - -#### Concept: sister - - This concept can be expressed by the following rule: - - if Y and Z have the same parent and Z is female, then Z - is the Y's sister. - -The ERESYE rule used to map this concept is: - - %% - %% if (Y and Z have the same parent X) and (Z is female) - %% then (Z is Y's sister) - %% - sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> - eresye:assert (Engine, {sister, Z, Y}). - - -Please note the guard, which is needed to ensure that when Y and Z are -bound to the same value, the rule is not activated (indeed this is -possible since the same fact can match both the first and second -'parent' pattern). - -#### Concept: brother - -Given the previous one, this concept is now quite simple to -implement: - - - %% - %% if (Y and Z have the same parent X) and (Z is male) - %% then (Z is Y's brother) - %% - brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> - eresye:assert (Engine, {brother, Z, Y}). - - -#### Concepts: grandmother and grandfather - -The former concept can be expressed by means of the rule: - - if X is Y's mother and Y is Z's parent, then X is Z's - grandmother.* The latter concept is now obvious. - -Both can be implemented using the following ERESYE rules: - - %% - %% if (X is Y's mother) and (Y is Z's parent) - %% then (X is Z's grandmother) - %% - grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandmother, X, Z}). - - %% - %% if (X is Y's father) and (Y is Z's parent) - %% then (X is Z's grandfather) - %% - grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandfather, X, Z}). - - -Instantiating the Engine and Populating the Knowledge Base ----------------------------------------------------------- - -After writing the rules, we need to: - -- instantiate the engine; -- add the rules above to the engine; -- populate the knowledge base with a set of initial facts. - -We do this in the function *start* below: - - start () -> - eresye:start (relatives), - lists:foreach (fun (X) -> - eresye:add_rule (relatives, {?MODULE, X}) - end, - [mother, father, brother, sister, - grandfather, grandmother]), - - eresye:assert (relatives, - [{male, bob}, {male, corrado}, {male, mark}, {male, caesar}, - {female, alice}, {female, sara}, {female, jane}, {female, anna}, - {parent, jane, bob}, {parent, corrado, bob}, - {parent, jane, mark}, {parent, corrado, mark}, - {parent, jane, alice}, {parent, corrado, alice}, - {parent, bob, caesar}, {parent, bob, anna}, - {parent, sara, casear}, {parent, sara, anna}]), - ok. - -As the listing reports, creating a new ERESYE engine implies to call -the function *eresye:start/1*, giving the name of the engine to be -created - -Then, we have to add the rules to the engine by using the function -*eresye:add_rule/2*: it takes two arguments, the name of the engine -and a tuple representing the function in the form *{Module, -FuncName}*; obviously the function *Module:FuncName* must be -exported. Function *add_rule* has to be called for each rule that has -to be added; for this reason, the code above has an iteration over the -list of rules written before. - -Finally, we populate the inference engine with a set of sample facts -by giving them, in a list, to the function *eresye:assert/2*. To test -our rules, we considered the relationships in the Figure below and -assert only the facts for *male*, *female* and *parent*. - -Testing the application ------------------------ - -The final complete code of our AI application is thus the following: - - - %%% - %%% relatives.erl - %%% - -module (relatives). - -compile ([export_all]). - - %% - %% if (X is female) and (X is Y's parent) then (X is Y's mother) - %% - mother (Engine, {female, X}, {parent, X, Y}) -> - eresye:assert (Engine, {mother, X, Y}). - - - %% - %% if (X is male) and (X is Y's parent) then (X is Y's father) - %% - father (Engine, {male, X}, {parent, X, Y}) -> - eresye:assert (Engine, {father, X, Y}). - - - - %% - %% if (Y and Z have the same parent X) and (Z is female) - %% then (Z is Y's sister) - %% - sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> - eresye:assert (Engine, {sister, Z, Y}). - - - - %% - %% if (Y and Z have the same parent X) and (Z is male) - %% then (Z is Y's brother) - %% - brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> - eresye:assert (Engine, {brother, Z, Y}). - - - %% - %% if (X is Y's father) and (Y is Z's parent) - %% then (X is Z's grandfather) - %% - grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandfather, X, Z}). - - - %% - %% if (X is Y's mother) and (Y is Z's parent) - %% then (X is Z's grandmother) - %% - grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandmother, X, Z}). - - start () -> - eresye:start (relatives), - lists:foreach (fun (X) -> - eresye:add_rule (relatives, {?MODULE, X}) - end, - [mother, father, - brother, sister, - grandfather, grandmother]), - - eresye:assert (relatives, - [{male, bob}, - {male, corrado}, - {male, mark}, - {male, caesar}, - {female, alice}, - {female, sara}, - {female, jane}, - {female, anna}, - {parent, jane, bob}, - {parent, corrado, bob}, - {parent, jane, mark}, - {parent, corrado, mark}, - {parent, jane, alice}, - {parent, corrado, alice}, - {parent, bob, caesar}, - {parent, bob, anna}, - {parent, sara, casear}, - {parent, sara, anna}]), - ok. - -Now it's time to test our application: - - - Erlang (BEAM) emulator version 5.5 [source] [async-threads:0] [hipe] - - Eshell V5.5 (abort with ^G) - 1> c(relatives). - {ok,relatives} - 2> relatives:start(). - ok - 3> - -Following the call to function *relatives:start/0*, the engine is -created and populated; if no errors occurred, the rules should have -been processed and the new facts derived. To check this, we can use -the function *eresye:get_kb/1*, which returns the list of facts -asserted into the knowledge base of a given engine: - - - 4> eresye:get_kb(relatives). - [{brother,bob,mark}, - {sister,alice,bob}, - {sister,alice,mark}, - {brother,bob,alice}, - {brother,mark,alice}, - {grandmother,jane,caesar}, - {grandfather,corrado,caesar}, - {grandmother,jane,anna}, - {grandfather,corrado,anna}, - {sister,anna,caesar}, - {brother,caesar,anna}, - {sister,anna,casear}, - {mother,sara,anna}, - {mother,sara,casear}, - {parent,sara,anna}, - {father,bob,anna}, - {parent,sara,casear}, - {father,bob,caesar}, - {parent,bob,anna}, - {father,corrado,alice}, - {parent,bob,caesar}, - {mother,jane,alice}, - {parent,corrado,alice}, - {father,corrado,mark}, - {parent,jane,alice}, - {mother,jane,mark}, - {parent,corrado|...}, - {brother|...}, - {...}|...] - 5> - -The presence of facts representing concepts like *father*, *sister*, -etc., proves that the rules seems to be working as expected. - -We can however query the knowledge base using specific fact templates. -For example, if we want to know who are Alice's brothers, we can use -the function *eresye:query_kb/2* as follows: - - - 6> eresye:query_kb(relatives, {brother, '_', alice}). - [{brother,bob,alice},{brother,mark,alice}] - 7> - -The facts returned conform to the relationships depicted in the figure -above, thus proving that the rules written are really working. - -As the example shows, function *eresye:query_kb/2* takes the engine -name as the first argument, while, for the second parameter, a tuple -has to be specified, representing the fact template to be matched; in -such a tuple, the atom *'_'* plays the role of a wildcard. However, to -specify a more complex matching, a *fun* can be used as a tuple -element; this *fun* has to return a boolean value which indicates if -the element matches the template. For example, to select both Alice's -and Anna's brothers, we can use the following function call: - - - 7> eresye:query_kb(relatives, {brother, '_', fun (X) -> (X == alice) or (X == anna) end}). - [{brother,bob,alice},{brother,mark,alice},{brother,caesar,anna}] - 8> - -Deriving new concepts by means of rules ---------------------------------------- - -#### Concept: 'mother' - -The rule to derive the concept of mother is quite straightforward: - - if X is female and X is Y's parent then X is Y's mother. - -From the point of view of ERESYE, since knowledge is stored in the -*knowledge base* of the engine, the rule above is translated into the -following one: *if the facts *{female, X}* and *{parent, X, Y}* are -**asserted** in the knowledge base, then we assert the fact *{mother, -X, Y}*.* - -The rule *mother* can be thus written as follows: - - - %% - %% if (X is female) and (X is Y's parent) then (X is Y's mother) - %% - mother (Engine, {female, X}, {parent, X, Y}) -> - eresye:assert (Engine, {mother, X, Y}). - -#### Concept: 'father' - -This concept can be easily derived by means of the following rule: - - %% - %% if (X is male) and (X is Y's parent) then (X is Y's father) - %% - father (Engine, {male, X}, {parent, X, Y}) -> - eresye:assert (Engine, {father, X, Y}). - - -#### Concept: 'sister' - -This concept can be expressed by the following rule: - - if Y and Z have the same parent and Z is female, then Z is the Y's - sister. - -The ERESYE rule used to map this concept is: - - %% - %% if (Y and Z have the same parent X) and (Z is female) - %% then (Z is Y's sister) - %% - sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z -> - eresye:assert (Engine, {sister, Z, Y}). - -Please note the guard, which is needed to ensure that when Y and Z are -bound to the same value, the rule is not activated (indeed this is possible -since the same fact can match both the first and second -'parent' pattern). - -#### Concept: 'brother' - - Given the previous one, this concept is now quite simple to -implement: - - %% - %% if (Y and Z have the same parent X) and (Z is male) - %% then (Z is Y's brother) - %% - brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z -> - eresye:assert (Engine, {brother, Z, Y}). - - -#### Concepts: 'grandmother' and 'grandfather' - -The former concept can be expressed by means of the rule: - - if X is Y's mother and Y is Z's parent, then X is Z's grandmother. - -The latter concept is now obvious. Both can be implemented using the -following ERESYE rules: - - %% - %% if (X is Y's mother) and (Y is Z's parent) - %% then (X is Z's grandmother) - %% - grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandmother, X, Z}). - - %% - %% if (X is Y's father) and (Y is Z's parent) - %% then (X is Z's grandfather) - %% - grandfather (Engine, {father, X, Y}, {parent, Y, Z}) -> - eresye:assert (Engine, {grandfather, X, Z}). - - -Conclusions ------------ - -This HowTo not only shows how to use the ERESYE engine to write an AI -application, but also highlights the versatility of the Erlang language: -the characteristics of functional and symbolic programming, together with -the possibility of performing *introspection* of function declaration, -can be successfully exploited for application domains which are completely -new for Erlang but can surely be very interesting. - +Erlware commons can best be described as an extension to the stdlib +application that is distributed with Erlang. These are things that we +at Erlware have found useful for production applications but are not +included with the distribution. We hope that as things in this library +prove themselves useful, they will make their way into the main Erlang +distribution. However, whether they do or not, we hope that this +application will prove generally useful. + +Goals for the project +--------------------- + +* Generally Useful Code +* High Quality +* Well Documented +* Well Tested From 144bc031ed5b8f582511d041acf9f36981bbe419 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 20 Feb 2012 14:06:24 -0600 Subject: [PATCH 011/240] Add a minimal makefile to the system Signed-off-by: Jordan Wilberding --- Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b473d7f --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +ERLC=`which erlc` +BEAMDIR=./ebin +ERLCFLAGS=+debug_info -pa $(BEAMDIR) +SRCDIR=src + +.PHONY=all clean + +all: + @echo "Erlware Commons is maintained with Sinan, its much better to use " + @echo "sinan to build than this makefile. This is here just to get " + @echo "get you started." + $(ERLC) $(ERLCFLAGS) -o $(BEAMDIR) $(SRCDIR)/ec_dictionary.erl; + $(ERLC) $(ERLCFLAGS) -o $(BEAMDIR) $(SRCDIR)/*.erl ; + +clean: + rm $(BEAMDIR)/*.beam + rm -rf erl_crush.dump \ No newline at end of file From 23de64a3cdc8d1b2d250e37a631a0b71b9fc4599 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 20 Feb 2012 14:07:13 -0600 Subject: [PATCH 012/240] Version bump 0.6.1 Signed-off-by: Jordan Wilberding --- ebin/erlware_commons.app | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index 6031e94..985374f 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.6.0"}, + {vsn, "0.6.1"}, {modules, [ ec_talk, ec_lists, From 30184d4f77d77e8d1a3e98d864f46398dc34e9e1 Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Fri, 23 Mar 2012 02:18:50 -0500 Subject: [PATCH 013/240] Fix for 12am and 12pm. 12am should be hour 0, 12pm should be hour 12. Signed-off-by: Eric Merritt --- src/ec_date.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ec_date.erl b/src/ec_date.erl index 7aeac3f..689377c 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -247,7 +247,9 @@ tokenise([Else | Rest], Acc) -> tokenise(Rest, [{bad_token, Else} | Acc]). hour(Hour, []) -> Hour; +hour(12, [am]) -> 0; hour(Hour, [am]) -> Hour; +hour(12, [pm]) -> 12; hour(Hour, [pm]) -> Hour+12. -spec format(string(),datetime(),list()) -> string(). @@ -541,6 +543,10 @@ basic_parse_test_() -> parse("1:15", ?DATE)), ?_assertEqual({{2001,3,10}, {1,15,0}}, parse("1:15 am", ?DATE)), + ?_assertEqual({{2001,3,10}, {0,15,0}}, + parse("12:15 am", ?DATE)), + ?_assertEqual({{2001,3,10}, {12,15,0}}, + parse("12:15 pm", ?DATE)), ?_assertEqual({{2001,3,10}, {3,45,39}}, parse("3:45:39", ?DATE)), ?_assertEqual({{1963,4,23}, {17,16,17}}, From e7d175d0dbbcfc9b1b93f69cebfbc73c4b937905 Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Fri, 23 Mar 2012 02:09:39 -0500 Subject: [PATCH 014/240] Add support for shorter times (7PM, 7AM, 7a, 7p) --- src/ec_date.erl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/ec_date.erl b/src/ec_date.erl index 689377c..8d79c34 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -109,6 +109,8 @@ parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> {Date, {hour(Hour, PAM), Min, Sec}}; parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> {Date, {hour(Hour, PAM), Min, 0}}; +parse([Hour | PAM],{Date,_Time}, _Opts) when ?is_meridian(PAM) -> + {Date, {hour(Hour,PAM), 0, 0}}; %% Dates 23/april/1963 parse([Day,Month,Year], {_Date, Time}, _Opts) -> @@ -123,6 +125,20 @@ parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_world_sep(X) -> {{Year, Month, Day}, Time}; %% Date/Times 22 Aug 2008 6:35 PM +%% Time is "7 PM" +parse([Year,X,Month,X,Day,Hour | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso + (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; +parse([Day,X,Month,X,Year,Hour | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso ?is_world_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; +parse([Month,X,Day,X,Year,Hour | PAM], _Date, _Opts) + when ?is_meridian(PAM) andalso ?is_us_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; + +%% Time is "6:35 PM" parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) @@ -135,6 +151,7 @@ parse([Month,X,Day,X,Year,Hour,$:,Min | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso ?is_us_sep(X) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; +%% Time is "6:35:15 PM" parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) @@ -148,6 +165,9 @@ parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; +parse([Day,Month,Year,Hour | PAM], _Now, _Opts) + when ?is_meridian(PAM) -> + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; parse([Day,Month,Year,Hour,$:,Min | PAM], _Now, _Opts) when ?is_meridian(PAM) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; @@ -203,6 +223,8 @@ tokenise([$/ | Rest], Acc) -> tokenise(Rest, [ $/ | Acc]); tokenise([$- | Rest], Acc) -> tokenise(Rest, [ $- | Acc]); tokenise("AM"++Rest, Acc) -> tokenise(Rest, [am | Acc]); tokenise("PM"++Rest, Acc) -> tokenise(Rest, [pm | Acc]); +tokenise("A"++Rest, Acc) -> tokenise(Rest, [am | Acc]); +tokenise("P"++Rest, Acc) -> tokenise(Rest, [pm | Acc]); %% Postel's Law %% @@ -521,22 +543,32 @@ basic_parse_test_() -> [ ?_assertEqual({{2008,8,22}, {17,16,17}}, parse("22nd of August 2008", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("22-Aug-2008 6 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22-Aug-2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,12}}, parse("22-Aug-2008 6:35:12 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("August/22/2008 6 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("August/22/2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22 August 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("22 Aug 2008 6AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22 Aug 2008 6:35AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22 Aug 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("22 Aug 2008 6", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("22 Aug 2008 6:35", ?DATE)), ?_assertEqual({{2008,8,22}, {18,35,0}}, parse("22 Aug 2008 6:35 PM", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,0,0}}, + parse("22 Aug 2008 6 PM", ?DATE)), ?_assertEqual({{2001,3,10}, {11,15,0}}, parse("11:15", ?DATE)), ?_assertEqual({{2001,3,10}, {1,15,0}}, @@ -595,14 +627,24 @@ parse_with_days_test_() -> parse("Sun 22-Aug-2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("THURSDAY, 22-August-2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,0,0}}, + parse("THURSDAY, 22-August-2008 6 pM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("THU 22 August 2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("FRi 22 Aug 2008 6:35AM", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("FRi 22 Aug 2008 6AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("Wednesday 22 Aug 2008 6:35 AM", ?DATE)), ?_assertEqual({{2008,8,22}, {6,35,0}}, parse("Monday 22 Aug 2008 6:35", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("Monday 22 Aug 2008 6", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,0,0}}, + parse("Monday 22 Aug 2008 6p", ?DATE)), + ?_assertEqual({{2008,8,22}, {6,0,0}}, + parse("Monday 22 Aug 2008 6a", ?DATE)), ?_assertEqual({{2008,8,22}, {18,35,0}}, parse("Mon, 22 Aug 2008 6:35 PM", ?DATE)) ]. From 26a2e91d4aeea3435fdc042765cd027ad7338ba0 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 23 Mar 2012 10:01:33 -0500 Subject: [PATCH 015/240] Version bump 0.6.2 --- ebin/erlware_commons.app | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ebin/erlware_commons.app b/ebin/erlware_commons.app index 985374f..4c4b057 100644 --- a/ebin/erlware_commons.app +++ b/ebin/erlware_commons.app @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.6.1"}, + {vsn, "0.6.2"}, {modules, [ ec_talk, ec_lists, From c828f7415a40150f7fdee562d142762fccd843f4 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:59:46 -0500 Subject: [PATCH 016/240] Migrate erlware_commons to rebar support --- Makefile | 17 ----------------- rebar.config | 3 +++ .../erlware_commons.app.src | 2 +- 3 files changed, 4 insertions(+), 18 deletions(-) delete mode 100644 Makefile create mode 100644 rebar.config rename ebin/erlware_commons.app => src/erlware_commons.app.src (96%) diff --git a/Makefile b/Makefile deleted file mode 100644 index b473d7f..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -ERLC=`which erlc` -BEAMDIR=./ebin -ERLCFLAGS=+debug_info -pa $(BEAMDIR) -SRCDIR=src - -.PHONY=all clean - -all: - @echo "Erlware Commons is maintained with Sinan, its much better to use " - @echo "sinan to build than this makefile. This is here just to get " - @echo "get you started." - $(ERLC) $(ERLCFLAGS) -o $(BEAMDIR) $(SRCDIR)/ec_dictionary.erl; - $(ERLC) $(ERLCFLAGS) -o $(BEAMDIR) $(SRCDIR)/*.erl ; - -clean: - rm $(BEAMDIR)/*.beam - rm -rf erl_crush.dump \ No newline at end of file diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..27aa310 --- /dev/null +++ b/rebar.config @@ -0,0 +1,3 @@ +{erl_opts, + [debug_info, + warnings_as_errors]}. \ No newline at end of file diff --git a/ebin/erlware_commons.app b/src/erlware_commons.app.src similarity index 96% rename from ebin/erlware_commons.app rename to src/erlware_commons.app.src index 4c4b057..a10e939 100644 --- a/ebin/erlware_commons.app +++ b/src/erlware_commons.app.src @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.6.2"}, + {vsn, "0.7.0"}, {modules, [ ec_talk, ec_lists, From 3e6357aea9d4bd8fdc7dc02abd294976cb1ec7b4 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:54:12 -0500 Subject: [PATCH 017/240] add . files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 55a8799..6846738 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.* _build erl_crash.dump *.pyc From 10557e421e6a85ff59439b0c21d23d3a5f036639 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:54:46 -0500 Subject: [PATCH 018/240] make mkdtemp a lot more secure (still not fully secure but more). --- src/ec_file.erl | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index f4d9d88..f27b2ce 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -109,14 +109,21 @@ is_symlink(Path) -> %% function of the same name. -spec mkdtemp() -> TmpDirPath::path(). mkdtemp() -> - UniqueNumber = integer_to_list(element(3, now())), + random:seed(now()), + UniqueNumber = erlang:integer_to_list(erlang:trunc(random:uniform() * 1000000000000)), TmpDirPath = filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]), - try - ok = mkdir_path(TmpDirPath), - TmpDirPath - catch - _C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, [])) + + case filelib:is_dir(TmpDirPath) of + true -> + throw(?UEX({mkdtemp_failed, file_exists}, "tmp directory exists", [])); + false -> + try + ok = mkdir_path(TmpDirPath), + TmpDirPath + catch + _C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, [])) + end end. From 261fb422f9e2144d36023e153518e7ca4febdb2c Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:55:07 -0500 Subject: [PATCH 019/240] fix eunit tests so that they actually work and run --- src/ec_file.erl | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index f27b2ce..f50695f 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -304,23 +304,20 @@ hex0(I) -> $0 + I. -include_lib("eunit/include/eunit.hrl"). setup_test() -> - case filelib:is_dir("/tmp/ec_file") of - true -> - remove("/tmp/ec_file", [recursive]); - false -> - ok - end, - mkdir_path("/tmp/ec_file/dir"), - ?assertMatch(false, is_symlink("/tmp/ec_file/dir")), - ?assertMatch(true, filelib:is_dir("/tmp/ec_file/dir")). - + Dir = mkdtemp(), + mkdir_path(Dir), + ?assertMatch(false, is_symlink(Dir)), + ?assertMatch(true, filelib:is_dir(Dir)). md5sum_test() -> ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). file_test() -> - TermFile = "/tmp/ec_file/dir/file.term", - TermFileCopy = "/tmp/ec_file/dircopy/file.term", + Dir = mkdtemp(), + TermFile = filename:join(Dir, "ec_file/dir/file.term"), + TermFileCopy = filename:join(Dir, "ec_file/dircopy/file.term"), + filelib:ensure_dir(TermFile), + filelib:ensure_dir(TermFileCopy), write_term(TermFile, "term"), ?assertMatch("term", consult(TermFile)), ?assertMatch(<<"\"term\". ">>, read(TermFile)), @@ -330,11 +327,12 @@ file_test() -> ?assertMatch("term", consult(TermFileCopy)). teardown_test() -> - remove("/tmp/ec_file", [recursive]), - ?assertMatch(false, filelib:is_dir("/tmp/ec_file")). + Dir = mkdtemp(), + remove(Dir, [recursive]), + ?assertMatch(false, filelib:is_dir(Dir)). setup_base_and_target() -> - {ok, BaseDir} = ewl_file:create_tmp_dir("/tmp"), + BaseDir = mkdtemp(), DummyContents = <<"This should be deleted">>, SourceDir = filename:join([BaseDir, "source"]), ok = file:make_dir(SourceDir), @@ -351,17 +349,12 @@ setup_base_and_target() -> find_test() -> %% Create a directory in /tmp for the test. Clean everything afterwards + {BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(), + ?assertMatch([Name2, + Name3, + Name1], + find(BaseDir, "file[a-z]+\$")), + remove(BaseDir, [recursive]). - {setup, - fun setup_base_and_target/0, - fun ({BaseDir, _, _}) -> - ewl_file:delete_dir(BaseDir) - end, - fun ({BaseDir, _, {Name1, Name2, Name3, _}}) -> - ?assertMatch([Name2, - Name3, - Name1], - ewl_file:find(BaseDir, "file[a-z]+\$")) - end}. -endif. From b4eb83cf53fed2ce113e04c1cc21b64d62ca02c7 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:56:45 -0500 Subject: [PATCH 020/240] make insecure nature of ec_file:mkdtemp obvious fixes erlware/erlware_commons#16 --- src/ec_file.erl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index f50695f..f26149e 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -9,7 +9,7 @@ -export([ copy/2, copy/3, - mkdtemp/0, + insecure_mkdtemp/0, mkdir_path/1, find/2, is_symlink/1, @@ -107,8 +107,8 @@ is_symlink(Path) -> %% @doc make a unique temorory directory. Similar function to BSD stdlib %% function of the same name. --spec mkdtemp() -> TmpDirPath::path(). -mkdtemp() -> +-spec insecure_mkdtemp() -> TmpDirPath::path(). +insecure_mkdtemp() -> random:seed(now()), UniqueNumber = erlang:integer_to_list(erlang:trunc(random:uniform() * 1000000000000)), TmpDirPath = @@ -304,7 +304,7 @@ hex0(I) -> $0 + I. -include_lib("eunit/include/eunit.hrl"). setup_test() -> - Dir = mkdtemp(), + Dir = insecure_mkdtemp(), mkdir_path(Dir), ?assertMatch(false, is_symlink(Dir)), ?assertMatch(true, filelib:is_dir(Dir)). @@ -313,7 +313,7 @@ md5sum_test() -> ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). file_test() -> - Dir = mkdtemp(), + Dir = insecure_mkdtemp(), TermFile = filename:join(Dir, "ec_file/dir/file.term"), TermFileCopy = filename:join(Dir, "ec_file/dircopy/file.term"), filelib:ensure_dir(TermFile), @@ -327,12 +327,12 @@ file_test() -> ?assertMatch("term", consult(TermFileCopy)). teardown_test() -> - Dir = mkdtemp(), + Dir = insecure_mkdtemp(), remove(Dir, [recursive]), ?assertMatch(false, filelib:is_dir(Dir)). setup_base_and_target() -> - BaseDir = mkdtemp(), + BaseDir = insecure_mkdtemp(), DummyContents = <<"This should be deleted">>, SourceDir = filename:join([BaseDir, "source"]), ok = file:make_dir(SourceDir), From 3e5eeb8cf7f70c0da80cf05e84bbf8f0965a5681 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 5 Jun 2012 17:59:19 -0500 Subject: [PATCH 021/240] add beam files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6846738..e85b87e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.beam .* _build erl_crash.dump From 9514b169933c6caf54a317a76f40ee9b06eeb379 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 3 Sep 2012 11:36:36 -0500 Subject: [PATCH 022/240] add rebar files to gitignore Signed-off-by: Jordan Wilberding --- .gitignore | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e85b87e..4e5856e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ -*.beam -.* +.erlware_commons_plt +.eunit/* +deps/* +doc/*.html +doc/*.css +doc/edoc-info +doc/erlang.png +ebin/* _build erl_crash.dump *.pyc From 51b5a41c631ea93e6a13befe036f3a13c93e8b3a Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 3 Sep 2012 11:33:40 -0500 Subject: [PATCH 023/240] add a full makefile that drives rebar Signed-off-by: Jordan Wilberding --- .gitignore | 1 + Makefile | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ rebar.config | 9 +++++++- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 4e5856e..65c6b5c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ doc/*.css doc/edoc-info doc/erlang.png ebin/* +.* _build erl_crash.dump *.pyc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..11948ac --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +# Copyright 2012 Erlware, LLC. All Rights Reserved. +# +# BSD License see COPYING + +ERL = $(shell which erl) + +ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/*/ebin + +REBAR=$(shell which rebar) + +ifeq ($(REBAR),) +$(error "Rebar not available on this system") +endif + +ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt + +.PHONY: all compile doc clean eunit dialyzer typer shell distclean pdf get-deps escript + +all: compile eunit dialyzer + +get-deps: + $(REBAR) get-deps + $(REBAR) compile + +compile: + $(REBAR) skip_deps=true compile + +doc: compile + $(REBAR) skip_deps=true doc + +eunit: compile + $(REBAR) skip_deps=true eunit + +$(ERLWARE_COMMONS_PLT): + @echo Building local plt at $(ERLWARE_COMMONS_PLT) + @echo + - dialyzer --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \ + --apps erts kernel stdlib -r deps + +dialyzer: $(ERLWARE_COMMONS_PLT) + dialyzer --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src + +typer: + typer --plt $(ERLWARE_COMMONS_PLT) -r ./src + +shell: compile +# You often want *rebuilt* rebar tests to be available to the +# shell you have to call eunit (to get the tests +# rebuilt). However, eunit runs the tests, which probably +# fails (thats probably why You want them in the shell). This +# runs eunit but tells make to ignore the result. + - @$(REBAR) eunit + @$(ERL) $(ERLFLAGS) + +clean: + $(REBAR) clean + rm $(CURDIR)/doc/*.html + rm $(CURDIR)/doc/*.css + rm $(CURDIR)/doc/*.png + rm $(CURDIR)/doc/edoc-info + +distclean: clean + rm -rf $(ERLWARE_COMMONS_PLT) + rm -rvf $(CURDIR)/deps/* diff --git a/rebar.config b/rebar.config index 27aa310..6b037b1 100644 --- a/rebar.config +++ b/rebar.config @@ -1,3 +1,10 @@ +%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- + +%% These are all only compile time dependencies +{deps, [ + {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}} + ]}. + {erl_opts, [debug_info, - warnings_as_errors]}. \ No newline at end of file + warnings_as_errors]}. From d7b60ccf19c22169afd34cec4f5fad01e60f3611 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 3 Sep 2012 11:33:00 -0500 Subject: [PATCH 024/240] fix edoc errors in various modules Signed-off-by: Jordan Wilberding --- src/ec_assoc_list.erl | 2 +- src/ec_dict.erl | 4 +-- src/ec_dictionary.erl | 2 +- src/ec_gb_trees.erl | 84 +++++++++++++++++++++---------------------- src/ec_orddict.erl | 4 +-- src/ec_rbdict.erl | 2 +- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl index 0ea9d68..dc83d25 100644 --- a/src/ec_assoc_list.erl +++ b/src/ec_assoc_list.erl @@ -4,8 +4,8 @@ %%% @doc %%% provides an implementation of ec_dictionary using an association %%% list as a basy +%%% see ec_dictionary %%% @end -%%% @see ec_dictionary %%%------------------------------------------------------------------- -module(ec_assoc_list). diff --git a/src/ec_dict.erl b/src/ec_dict.erl index 2eb61e7..0cd119e 100644 --- a/src/ec_dict.erl +++ b/src/ec_dict.erl @@ -5,9 +5,9 @@ %%% This provides an implementation of the ec_dictionary type using %%% erlang dicts as a base. The function documentation for %%% ec_dictionary applies here as well. +%%% see ec_dictionary +%%% see dict %%% @end -%%% @see ec_dictionary -%%% @see dict %%%------------------------------------------------------------------- -module(ec_dict). diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl index bc2fc91..771bec9 100644 --- a/src/ec_dictionary.erl +++ b/src/ec_dictionary.erl @@ -83,7 +83,7 @@ has_key(Key, #dict_t{callback = Mod, data = Data}) -> %% %% @param Dict The dictionary object to return the value from %% @param Key The key requested -%% @throws not_found when the key does not exist +%% when the key does not exist @throws not_found -spec get(key(K), dictionary(K, V)) -> value(V). get(Key, #dict_t{callback = Mod, data = Data}) -> Mod:get(Key, Data). diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl index d9fa761..d7ec574 100644 --- a/src/ec_gb_trees.erl +++ b/src/ec_gb_trees.erl @@ -4,9 +4,9 @@ %%% @doc %%% This provides an implementation of the type ec_dictionary using %%% gb_trees as a backin +%%% see ec_dictionary +%%% see gb_trees %%% @end -%%% @see ec_dictionary -%%% @see gb_trees %%%------------------------------------------------------------------- -module(ec_gb_trees). @@ -14,16 +14,16 @@ %% API -export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). + has_key/2, + get/2, + get/3, + add/3, + remove/2, + has_value/2, + size/1, + to_list/1, + from_list/1, + keys/1]). -export_type([dictionary/2]). @@ -33,8 +33,8 @@ -opaque dictionary(K, V) :: {non_neg_integer(), ec_gb_tree_node(K, V)}. -type ec_gb_tree_node(K, V) :: 'nil' | {K, V, - ec_gb_tree_node(K, V), - ec_gb_tree_node(K, V)}. + ec_gb_tree_node(K, V), + ec_gb_tree_node(K, V)}. %%%=================================================================== %%% API @@ -57,10 +57,10 @@ new() -> -spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). has_key(Key, Data) -> case gb_trees:lookup(Key, Data) of - {value, _Val} -> - true; - none -> - false + {value, _Val} -> + true; + none -> + false end. %% @doc given a key return that key from the dictionary. If the key is @@ -68,27 +68,27 @@ has_key(Key, Data) -> %% %% @param Object The dictionary object to return the value from %% @param Key The key requested -%% @throws not_found when the key does not exist +%% when the key does not exist @throws not_found -spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> ec_dictionary:value(V). get(Key, Data) -> case gb_trees:lookup(Key, Data) of - {value, Value} -> - Value; - none -> - throw(not_found) + {value, Value} -> + Value; + none -> + throw(not_found) end. -spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::dictionary(K, V)) -> + ec_dictionary:value(V), + Object::dictionary(K, V)) -> ec_dictionary:value(V). get(Key, Default, Data) -> case gb_trees:lookup(Key, Data) of - {value, Value} -> - Value; - none -> - Default + {value, Value} -> + Value; + none -> + Default end. %% @doc add a new value to the existing dictionary. Return a new @@ -98,7 +98,7 @@ get(Key, Default, Data) -> %% @param Key the key to add %% @param Value the value to add -spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> + Object::dictionary(K, V)) -> dictionary(K, V). add(Key, Value, Data) -> gb_trees:enter(Key, Value, Data). @@ -129,7 +129,7 @@ size(Data) -> gb_trees:size(Data). -spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. + ec_dictionary:value(V)}]. to_list(Data) -> gb_trees:to_list(Data). @@ -137,10 +137,10 @@ to_list(Data) -> dictionary(K, V). from_list(List) when is_list(List) -> lists:foldl(fun({Key, Value}, Dict) -> - gb_trees:enter(Key, Value, Dict) - end, - gb_trees:empty(), - List). + gb_trees:enter(Key, Value, Dict) + end, + gb_trees:empty(), + List). -spec keys(dictionary(K,_V)) -> [ec_dictionary:key(K)]. keys(Data) -> @@ -189,12 +189,12 @@ add_test() -> Dict01 = ec_dictionary:add(Key1, Value1, Dict0), Dict02 = ec_dictionary:add(Key3, Value3, - ec_dictionary:add(Key2, Value2, - Dict01)), + ec_dictionary:add(Key2, Value2, + Dict01)), Dict1 = - ec_dictionary:add(Key5, Value5, - ec_dictionary:add(Key4, Value4, - Dict02)), + ec_dictionary:add(Key5, Value5, + ec_dictionary:add(Key4, Value4, + Dict02)), ?assertMatch(Value1, ec_dictionary:get(Key1, Dict1)), ?assertMatch(Value2, ec_dictionary:get(Key2, Dict1)), @@ -204,7 +204,7 @@ add_test() -> Dict2 = ec_dictionary:add(Key3, Value5, - ec_dictionary:add(Key2, Value4, Dict1)), + ec_dictionary:add(Key2, Value4, Dict1)), ?assertMatch(Value1, ec_dictionary:get(Key1, Dict2)), @@ -216,7 +216,7 @@ add_test() -> ?assertThrow(not_found, ec_dictionary:get(should_blow_up, Dict2)), ?assertThrow(not_found, ec_dictionary:get("This should blow up too", - Dict2)). + Dict2)). diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl index 51a7d40..9ae4a86 100644 --- a/src/ec_orddict.erl +++ b/src/ec_orddict.erl @@ -5,9 +5,9 @@ %%% This provides an implementation of the ec_dictionary type using %%% erlang orddicts as a base. The function documentation for %%% ec_dictionary applies here as well. +%%% see ec_dictionary +%%% see orddict %%% @end -%%% @see ec_dictionary -%%% @see orddict %%%------------------------------------------------------------------- -module(ec_orddict). diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl index bb89674..547e339 100644 --- a/src/ec_rbdict.erl +++ b/src/ec_rbdict.erl @@ -51,8 +51,8 @@ %%% l/rbalance, the colour, in store etc. is actually slower than not %%% doing it. Measured. %%% +%%% see ec_dictionary %%% @end -%%% @see ec_dictionary %%%------------------------------------------------------------------- -module(ec_rbdict). From 7e42c243b0cdd9680af444a7a6354643c6f1f43e Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sat, 8 Sep 2012 09:59:19 -0500 Subject: [PATCH 025/240] add travis support to the system Signed-off-by: Jordan Wilberding --- .travis.yml | 12 ++++++++++++ README.md | 4 ++++ 2 files changed, 16 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..35c5897 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: erlang +otp_release: + - R15B02 + - R15B01 + - R15B + +before_script: "make get-deps" +script: "make" +branches: + only: + - master + - next diff --git a/README.md b/README.md index 5681fe6..f2cab01 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ Erlware Commons =============== +Current Status +-------------- +[![Build Status](https://secure.travis-ci.org/erlware/erlware_commons.png)](http://travis-ci.org/erlware/erlware_commons) + Introduction ------------ From e035ae3dbf9562b3b61ea3989bfdab35e7b0c954 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 4 Sep 2012 20:27:19 -0500 Subject: [PATCH 026/240] fixes to dialyzer All types should now be correct and dialyzer runs successfully Signed-off-by: Jordan Wilberding --- Makefile | 4 ++-- src/ec_assoc_list.erl | 8 +++++--- src/ec_dict.erl | 6 ++++-- src/ec_dictionary.erl | 34 ++++++++++++++------------------ src/ec_file.erl | 45 ++++++++++++++++++++----------------------- src/ec_gb_trees.erl | 6 ++++-- src/ec_lists.erl | 2 +- src/ec_orddict.erl | 6 ++++-- src/ec_plists.erl | 25 +++++++++++++++--------- src/ec_rbdict.erl | 26 +++++++++++++------------ src/ec_semver.erl | 12 +++++++----- src/ec_talk.erl | 25 ++++++++++++++---------- 12 files changed, 107 insertions(+), 92 deletions(-) diff --git a/Makefile b/Makefile index 11948ac..d32718a 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ $(ERLWARE_COMMONS_PLT): @echo Building local plt at $(ERLWARE_COMMONS_PLT) @echo - dialyzer --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \ - --apps erts kernel stdlib -r deps + --apps erts kernel stdlib eunit -r deps dialyzer: $(ERLWARE_COMMONS_PLT) dialyzer --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src @@ -49,7 +49,7 @@ shell: compile # rebuilt). However, eunit runs the tests, which probably # fails (thats probably why You want them in the shell). This # runs eunit but tells make to ignore the result. - - @$(REBAR) eunit + - @$(REBAR) skip_deps=true eunit @$(ERL) $(ERLFLAGS) clean: diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl index dc83d25..80919aa 100644 --- a/src/ec_assoc_list.erl +++ b/src/ec_assoc_list.erl @@ -29,8 +29,10 @@ %%%=================================================================== %%% Types %%%=================================================================== --opaque dictionary(K, V) :: {ec_assoc_list, - [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(K, V) :: {ec_assoc_list, + [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. %%%=================================================================== %%% API @@ -82,7 +84,7 @@ remove(Key, {ec_assoc_list, Data}) -> has_value(Value, {ec_assoc_list, Data}) -> lists:keymember(Value, 2, Data). --spec size(Object::dictionary(_K, _V)) -> integer(). +-spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). size({ec_assoc_list, Data}) -> length(Data). diff --git a/src/ec_dict.erl b/src/ec_dict.erl index 0cd119e..1c5d319 100644 --- a/src/ec_dict.erl +++ b/src/ec_dict.erl @@ -31,7 +31,9 @@ %%%=================================================================== %%% Types %%%=================================================================== --opaque dictionary(_K, _V) :: dict(). +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(_K, _V) :: dict(). %%%=================================================================== %%% API @@ -88,7 +90,7 @@ has_value(Value, Data) -> false, Data). --spec size(Object::dictionary(_K, _V)) -> integer(). +-spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). size(Data) -> dict:size(Data). diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl index 771bec9..1061665 100644 --- a/src/ec_dictionary.erl +++ b/src/ec_dictionary.erl @@ -10,9 +10,6 @@ %%%------------------------------------------------------------------- -module(ec_dictionary). -%%% Behaviour Callbacks --export([behaviour_info/1]). - %% API -export([new/1, has_key/2, @@ -38,30 +35,27 @@ {callback, data}). --opaque dictionary(_K, _V) :: #dict_t{}. +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(_K, _V) :: #dict_t{}. -type key(T) :: T. -type value(T) :: T. +-callback new() -> any(). +-callback has_key(key(any()), any()) -> boolean(). +-callback get(key(any()), any()) -> any(). +-callback add(key(any()), value(any()), T) -> T. +-callback remove(key(any()), T) -> T. +-callback has_value(value(any()), any()) -> boolean(). +-callback size(any()) -> non_neg_integer(). +-callback to_list(any()) -> [{key(any()), value(any())}]. +-callback from_list([{key(any()), value(any())}]) -> any(). +-callback keys(any()) -> [key(any())]. + %%%=================================================================== %%% API %%%=================================================================== -%% @doc export the behaviour callbacks for this type -%% @private -behaviour_info(callbacks) -> - [{new, 0}, - {has_key, 2}, - {get, 2}, - {add, 3}, - {remove, 2}, - {has_value, 2}, - {size, 1}, - {to_list, 1}, - {from_list, 1}, - {keys, 1}]; -behaviour_info(_) -> - undefined. - %% @doc create a new dictionary object from the specified module. The %% module should implement the dictionary behaviour. %% diff --git a/src/ec_file.erl b/src/ec_file.erl index f26149e..cc40c07 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -23,7 +23,6 @@ ]). -export_type([ - path/0, option/0 ]). @@ -43,14 +42,13 @@ %%============================================================================ %% Types %%============================================================================ --type path() :: string(). --type option() :: [atom()]. - +-type option() :: recursive. +-type void() :: ok. %%%=================================================================== %%% API %%%=================================================================== %% @doc copy an entire directory to another location. --spec copy(path(), path(), Options::[option()]) -> ok. +-spec copy(file:name(), file:name(), Options::[option()]) -> void(). copy(From, To, []) -> copy(From, To); copy(From, To, [recursive] = Options) -> @@ -63,7 +61,7 @@ copy(From, To, [recursive] = Options) -> end. %% @doc copy a file including timestamps,ownership and mode etc. --spec copy(From::string(), To::string()) -> ok. +-spec copy(From::file:filename(), To::file:filename()) -> ok. copy(From, To) -> try ec_file_copy(From, To) @@ -81,7 +79,7 @@ md5sum(Value) -> %%
 %% Example: remove("./tmp_dir", [recursive]).
 %% 
--spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}. +-spec remove(file:name(), Options::[option()]) -> ok | {error, Reason::term()}. remove(Path, Options) -> try ok = ec_file_remove(Path, Options) @@ -90,12 +88,12 @@ remove(Path, Options) -> end. %% @doc delete a file. --spec remove(path()) -> ok | {error, Reason::term()}. +-spec remove(file:name()) -> ok | {error, Reason::term()}. remove(Path) -> remove(Path, []). %% @doc indicates witha boolean if the path supplied refers to symlink. --spec is_symlink(path()) -> boolean(). +-spec is_symlink(file:name()) -> boolean(). is_symlink(Path) -> case file:read_link_info(Path) of {ok, #file_info{type = symlink}} -> @@ -107,7 +105,7 @@ is_symlink(Path) -> %% @doc make a unique temorory directory. Similar function to BSD stdlib %% function of the same name. --spec insecure_mkdtemp() -> TmpDirPath::path(). +-spec insecure_mkdtemp() -> TmpDirPath::file:name(). insecure_mkdtemp() -> random:seed(now()), UniqueNumber = erlang:integer_to_list(erlang:trunc(random:uniform() * 1000000000000)), @@ -128,7 +126,7 @@ insecure_mkdtemp() -> %% @doc Makes a directory including parent dirs if they are missing. --spec mkdir_path(path()) -> ok. +-spec mkdir_path(file:name()) -> ok. mkdir_path(Path) -> %% We are exploiting a feature of ensuredir that that creates all %% directories up to the last element in the filename, then ignores @@ -144,7 +142,7 @@ mkdir_path(Path) -> %% @doc consult an erlang term file from the file system. %% Provide user readible exeption on failure. --spec consult(FilePath::path()) -> term(). +-spec consult(FilePath::file:name()) -> term(). consult(FilePath) -> case file:consult(FilePath) of {ok, [Term]} -> @@ -160,7 +158,7 @@ consult(FilePath) -> end. %% @doc read a file from the file system. Provide UEX exeption on failure. --spec read(FilePath::string()) -> binary(). +-spec read(FilePath::file:filename()) -> binary(). read(FilePath) -> try {ok, FileBin} = file:read_file(FilePath), @@ -173,7 +171,7 @@ read(FilePath) -> end. %% @doc write a file to the file system. Provide UEX exeption on failure. --spec write(FileName::string(), Contents::string()) -> ok. +-spec write(FileName::file:filename(), Contents::string()) -> ok. write(FileName, Contents) -> case file:write_file(FileName, Contents) of ok -> @@ -187,13 +185,13 @@ write(FileName, Contents) -> end. %% @doc write a term out to a file so that it can be consulted later. --spec write_term(string(), term()) -> ok. +-spec write_term(file:filename(), term()) -> ok. write_term(FileName, Term) -> write(FileName, lists:flatten(io_lib:fwrite("~p. ", [Term]))). %% @doc Finds files and directories that match the regexp supplied in %% the TargetPattern regexp. --spec find(FromDir::path(), TargetPattern::string()) -> [path()]. +-spec find(FromDir::file:name(), TargetPattern::string()) -> [file:name()]. find([], _) -> []; find(FromDir, TargetPattern) -> @@ -214,7 +212,7 @@ find(FromDir, TargetPattern) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== --spec find_in_subdirs(path(), string()) -> [path()]. +-spec find_in_subdirs(file:name(), string()) -> [file:name()]. find_in_subdirs(FromDir, TargetPattern) -> lists:foldl(fun(CheckFromDir, Acc) when CheckFromDir == FromDir -> @@ -228,14 +226,14 @@ find_in_subdirs(FromDir, TargetPattern) -> [], filelib:wildcard(filename:join(FromDir, "*"))). --spec ec_file_remove(path(), [{atom(), any()}]) -> ok. +-spec ec_file_remove(file:name(), [option()]) -> ok | {error, Reason::any()}. ec_file_remove(Path, Options) -> case lists:member(recursive, Options) of false -> file:delete(Path); true -> remove_recursive(Path, Options) end. --spec remove_recursive(path(), Options::list()) -> ok. +-spec remove_recursive(file:name(), Options::list()) -> ok. remove_recursive(Path, Options) -> case filelib:is_dir(Path) of false -> @@ -247,7 +245,7 @@ remove_recursive(Path, Options) -> ok = file:del_dir(Path) end. --spec tmp() -> path(). +-spec tmp() -> file:name(). tmp() -> case erlang:system_info(system_architecture) of "win32" -> @@ -257,7 +255,7 @@ tmp() -> end. %% Copy the subfiles of the From directory to the to directory. --spec copy_subfiles(path(), path(), [option()]) -> ok. +-spec copy_subfiles(file:name(), file:name(), [option()]) -> void(). copy_subfiles(From, To, Options) -> Fun = fun(ChildFrom) -> @@ -266,13 +264,13 @@ copy_subfiles(From, To, Options) -> end, lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). --spec ec_file_copy(path(), path()) -> ok. +-spec ec_file_copy(file:name(), file:name()) -> ok. ec_file_copy(From, To) -> {ok, _} = file:copy(From, To), {ok, FileInfo} = file:read_file_info(From), ok = file:write_file_info(To, FileInfo). --spec make_dir_if_dir(path()) -> ok. +-spec make_dir_if_dir(file:name()) -> ok. make_dir_if_dir(File) -> case filelib:is_dir(File) of true -> ok; @@ -356,5 +354,4 @@ find_test() -> find(BaseDir, "file[a-z]+\$")), remove(BaseDir, [recursive]). - -endif. diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl index d7ec574..7427740 100644 --- a/src/ec_gb_trees.erl +++ b/src/ec_gb_trees.erl @@ -30,7 +30,9 @@ %%%=================================================================== %%% Types %%%=================================================================== --opaque dictionary(K, V) :: {non_neg_integer(), ec_gb_tree_node(K, V)}. +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(K, V) :: {non_neg_integer(), ec_gb_tree_node(K, V)}. -type ec_gb_tree_node(K, V) :: 'nil' | {K, V, ec_gb_tree_node(K, V), @@ -124,7 +126,7 @@ has_value(Value, Data) -> %% @doc return the current number of key value pairs in the dictionary %% %% @param Object the object return the size for. --spec size(Object::dictionary(_K, _V)) -> integer(). +-spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). size(Data) -> gb_trees:size(Data). diff --git a/src/ec_lists.erl b/src/ec_lists.erl index 1545eeb..cbc1f0b 100644 --- a/src/ec_lists.erl +++ b/src/ec_lists.erl @@ -23,7 +23,7 @@ %% the third value is the element passed to the function. The purpose %% of this is to allow a list to be searched where some internal state %% is important while the input element is not. --spec search(fun(), list()) -> {ok, Result::term(), Element::term()}. +-spec search(fun(), list()) -> {ok, Result::term(), Element::term()} | not_found. search(Fun, [H|T]) -> case Fun(H) of {ok, Value} -> diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl index 9ae4a86..1244d60 100644 --- a/src/ec_orddict.erl +++ b/src/ec_orddict.erl @@ -31,7 +31,9 @@ %%%=================================================================== %%% Types %%%=================================================================== --opaque dictionary(K, V) :: [{K, V}]. +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(K, V) :: [{K, V}]. %%%=================================================================== %%% API @@ -88,7 +90,7 @@ has_value(Value, Data) -> false, Data). --spec size(Object::dictionary(_K, _V)) -> integer(). +-spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). size(Data) -> orddict:size(Data). diff --git a/src/ec_plists.erl b/src/ec_plists.erl index a90bc38..cd14697 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -13,6 +13,13 @@ filter/2, filter/3]). +-export_type([thunk/0]). + +%%============================================================================= +%% Types +%%============================================================================= +-type thunk() :: fun((any()) -> any()). + %%============================================================================= %% Public API %%============================================================================= @@ -25,7 +32,7 @@ map(Fun, List) -> map(Fun, List, infinity). --spec map(fun(), [any()], non_neg_integer()) -> [any()]. +-spec map(thunk(), [any()], timeout() | infinity) -> [any()]. map(Fun, List, Timeout) -> run_list_fun_in_parallel(map, Fun, List, Timeout). @@ -43,29 +50,29 @@ map(Fun, List, Timeout) -> %% 2> ftmap(fun(N) -> factorial(N) end, [1, 2, 1000000, "not num"], 100) %% [{value, 1}, {value, 2}, timeout, {badmatch, ...}] %% --spec ftmap(fun(), [any()]) -> [{value, any()} | any()]. +-spec ftmap(thunk(), [any()]) -> [{value, any()} | any()]. ftmap(Fun, List) -> ftmap(Fun, List, infinity). --spec ftmap(fun(), [any()], non_neg_integer()) -> [{value, any()} | any()]. +-spec ftmap(thunk(), [any()], timeout() | infinity) -> [{value, any()} | any()]. ftmap(Fun, List, Timeout) -> run_list_fun_in_parallel(ftmap, Fun, List, Timeout). %% @doc Returns a list of the elements in the supplied list which %% the function Fun returns true. A timeout is optional. In the %% event of a timeout the filter operation fails. --spec filter(fun(), [any()]) -> [any()]. +-spec filter(thunk(), [any()]) -> [any()]. filter(Fun, List) -> filter(Fun, List, infinity). --spec filter(fun(), [any()], integer()) -> [any()]. +-spec filter(thunk(), [any()], timeout() | infinity) -> [any()]. filter(Fun, List, Timeout) -> run_list_fun_in_parallel(filter, Fun, List, Timeout). %%============================================================================= %% Internal API %%============================================================================= --spec run_list_fun_in_parallel(atom(), fun(), [any()], integer()) -> [any()]. +-spec run_list_fun_in_parallel(atom(), thunk(), [any()], timeout() | infinity) -> [any()]. run_list_fun_in_parallel(ListFun, Fun, List, Timeout) -> LocalPid = self(), Pids = @@ -79,7 +86,7 @@ run_list_fun_in_parallel(ListFun, Fun, List, Timeout) -> end, List), gather(ListFun, Pids). --spec wait(pid(), fun(), any(), integer()) -> any(). +-spec wait(pid(), thunk(), any(), timeout() | infinity) -> any(). wait(Parent, Fun, E, Timeout) -> WaitPid = self(), Child = spawn(fun() -> @@ -88,7 +95,7 @@ wait(Parent, Fun, E, Timeout) -> wait(Parent, Child, Timeout). --spec wait(pid(), pid(), integer()) -> any(). +-spec wait(pid(), pid(), timeout() | infinity) -> any(). wait(Parent, Child, Timeout) -> receive {Child, Ret} -> @@ -146,7 +153,7 @@ filter_gather([{Pid, E} | Rest]) -> filter_gather([]) -> []. --spec do_f(pid(), fun(), any()) -> no_return(). +-spec do_f(pid(), thunk(), any()) -> no_return(). do_f(Parent, F, E) -> try Result = F(E), diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl index 547e339..1bfcecc 100644 --- a/src/ec_rbdict.erl +++ b/src/ec_rbdict.erl @@ -68,12 +68,13 @@ %%%=================================================================== %%% Types %%%=================================================================== - --opaque dictionary(K, V) :: empty | {color(), - dictionary(K, V), - ec_dictionary:key(K), - ec_dictionary:value(V), - dictionary(K, V)}. +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type dictionary(K, V) :: empty | {color(), + dictionary(K, V), + ec_dictionary:key(K), + ec_dictionary:value(V), + dictionary(K, V)}. -type color() :: r | b. @@ -116,7 +117,7 @@ get(K, Default, {_, _, K1, _, Right}) when K > K1 -> get(_, _, {_, _, _, Val, _}) -> Val. --spec add(ec_dicitonary:key(K), ec_dictionary:value(V), +-spec add(ec_dictionary:key(K), ec_dictionary:value(V), dictionary(K, V)) -> dictionary(K, V). add(Key, Value, Dict) -> {_, L, K1, V1, R} = add1(Key, Value, Dict), @@ -133,7 +134,7 @@ has_value(Value, Dict) -> end, false, Dict). --spec size(dictionary(_K, _V)) -> integer(). +-spec size(dictionary(_K, _V)) -> non_neg_integer(). size(T) -> size1(T). @@ -227,7 +228,7 @@ erase_aux(K, {r, A, Xk, Xv, B}) -> end. -spec erase_min(dictionary(K, V)) -> - {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean}. + {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean()}. erase_min({b, empty, Xk, Xv, empty}) -> {empty, {Xk, Xv}, true}; erase_min({b, empty, Xk, Xv, {r, A, Yk, Yv, B}}) -> @@ -274,7 +275,8 @@ unbalright(b, A, Xk, Xv, D}, false}. --spec fold(fun(), dictionary(K, V), dictionary(K, V)) -> dictionary(K, V). +-spec fold(fun((ec_dictionary:key(K), ec_dictionary:value(V), any()) -> any()), + any(), dictionary(K, V)) -> any(). fold(_, Acc, empty) -> Acc; fold(F, Acc, {_, A, Xk, Xv, B}) -> fold(F, F(Xk, Xv, fold(F, Acc, B)), A). @@ -295,7 +297,7 @@ to_list({_, A, Xk, Xv, B}, List) -> %% Balance a tree afer (possibly) adding a node to the left/right. -spec lbalance(color(), dictionary(K, V), - ec_dictinary:key(K), ec_dictionary:value(V), + ec_dictionary:key(K), ec_dictionary:value(V), dictionary(K, V)) -> dictionary(K, V). lbalance(b, {r, {r, A, Xk, Xv, B}, Yk, Yv, C}, Zk, Zv, @@ -307,7 +309,7 @@ lbalance(b, {r, A, Xk, Xv, {r, B, Yk, Yv, C}}, Zk, Zv, lbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. -spec rbalance(color(), dictionary(K, V), - ec_dictinary:key(K), ec_dictionary:value(V), + ec_dictionary:key(K), ec_dictionary:value(V), dictionary(K, V)) -> dictionary(K, V). rbalance(b, A, Xk, Xv, diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 77b43cd..49a16a9 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -20,11 +20,13 @@ %%%=================================================================== -type semvar() :: string(). --type parsed_semvar() :: {MajorVsn::string(), - MinorVsn::string(), - PatchVsn::string(), +-type parsed_semvar() :: {MajorVsn::integer(), + MinorVsn::integer(), + PatchVsn::integer(), PathString::string()}. +-type semver_tokens() :: {string(), string(), string(), string()}. + %%%=================================================================== %%% API %%%=================================================================== @@ -41,7 +43,7 @@ compare(VsnA, VsnB) -> %%% Internal Functions %%%=================================================================== --spec tokens(semvar()) -> parsed_semvar(). +-spec tokens(semvar()) -> semver_tokens(). tokens(Vsn) -> [MajorVsn, MinorVsn, RawPatch] = string:tokens(Vsn, "."), {PatchVsn, PatchString} = split_patch(RawPatch), @@ -62,7 +64,7 @@ split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> split_patch(PatchStr, {PatchVsn, ""}) -> {PatchVsn, PatchStr}. --spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean(). +-spec compare_toks(semver_tokens(), semver_tokens()) -> boolean(). compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) -> compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA}, {to_int(MajB), to_int(MinB), to_int(PVB), PSB}). diff --git a/src/ec_talk.erl b/src/ec_talk.erl index 0823169..4a82d1b 100644 --- a/src/ec_talk.erl +++ b/src/ec_talk.erl @@ -49,7 +49,7 @@ %%============================================================================ -type prompt() :: string(). -type type() :: boolean | number | string. --type supported() :: string() | boolean() | number(). +-type supported() :: boolean() | number() | string(). %%============================================================================ %% API @@ -100,8 +100,11 @@ ask_default(Prompt, string, Default) -> %% between min and max. -spec ask(prompt(), number(), number()) -> number(). ask(Prompt, Min, Max) - when is_list(Prompt), is_number(Min), is_number(Max) -> - Res = ask(Prompt, fun get_integer/1, none), + when erlang:is_list(Prompt), + erlang:is_number(Min), + erlang:is_number(Max), + Min =< Max -> + Res = ask_convert(Prompt, fun get_integer/1, number, none), case (Res >= Min andalso Res =< Max) of true -> Res; @@ -115,14 +118,16 @@ ask(Prompt, Min, Max) %% ============================================================================ %% @doc Actually does the work of asking, checking result and %% translating result into the requested format. --spec ask_convert(prompt(), fun(), type(), supported()) -> supported(). +-spec ask_convert(prompt(), fun((any()) -> any()), type(), supported() | none) -> supported(). ask_convert(Prompt, TransFun, Type, Default) -> - NewPrompt = Prompt ++ case Default of - none -> - []; - Default -> - " (" ++ sin_utils:term_to_list(Default) ++ ")" - end ++ "> ", + NewPrompt = + erlang:binary_to_list(erlang:iolist_to_binary([Prompt, + case Default of + none -> + []; + Default -> + [" (", io_lib:format("~p", [Default]) , ")"] + end, "> "])), Data = string:strip(string:strip(io:get_line(NewPrompt)), both, $\n), Ret = TransFun(Data), case Ret of From cf8cad00df8841ea6af60562a4a6d122a508cbcc Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 4 Sep 2012 20:27:31 -0500 Subject: [PATCH 027/240] make sure ec_dictionary gets built first Signed-off-by: Jordan Wilberding --- rebar.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rebar.config b/rebar.config index 6b037b1..ded76c0 100644 --- a/rebar.config +++ b/rebar.config @@ -5,6 +5,8 @@ {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}} ]}. +{erl_first_files, ["ec_dictionary"]}. + {erl_opts, [debug_info, warnings_as_errors]}. From a2672cafb135afa7756767e46658521bfd7556c8 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 4 Sep 2012 20:32:39 -0500 Subject: [PATCH 028/240] minor whitespace cleanup Signed-off-by: Jordan Wilberding --- src/ec_assoc_list.erl | 18 +++++++++--------- src/ec_orddict.erl | 28 ++++++++++++++-------------- src/ec_rbdict.erl | 22 +++++++++++----------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl index 80919aa..e9bd0cc 100644 --- a/src/ec_assoc_list.erl +++ b/src/ec_assoc_list.erl @@ -47,12 +47,12 @@ has_key(Key, {ec_assoc_list, Data}) -> lists:keymember(Key, 1, Data). -spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> - ec_dictionary:value(V). + ec_dictionary:value(V). get(Key, {ec_assoc_list, Data}) -> case lists:keyfind(Key, 1, Data) of {Key, Value} -> Value; - false -> + false -> throw(not_found) end. @@ -64,19 +64,19 @@ get(Key, Default, {ec_assoc_list, Data}) -> case lists:keyfind(Key, 1, Data) of {Key, Value} -> Value; - false -> + false -> Default end. -spec add(ec_dictionary:key(K), ec_dictionary:value(V), Object::dictionary(K, V)) -> - dictionary(K, V). + dictionary(K, V). add(Key, Value, {ec_assoc_list, _Data}=Dict) -> {ec_assoc_list, Rest} = remove(Key,Dict), {ec_assoc_list, [{Key, Value} | Rest ]}. -spec remove(ec_dictionary:key(K), Object::dictionary(K, _V)) -> - dictionary(K, _V). + dictionary(K, _V). remove(Key, {ec_assoc_list, Data}) -> {ec_assoc_list, lists:keydelete(Key, 1, Data)}. @@ -91,15 +91,15 @@ size({ec_assoc_list, Data}) -> -spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), ec_dictionary:value(V)}]. to_list({ec_assoc_list, Data}) -> - Data. + Data. -spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). + dictionary(K, V). from_list(List) when is_list(List) -> {ec_assoc_list, List}. -spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. keys({ec_assoc_list, Data}) -> lists:map(fun({Key, _Value}) -> - Key - end, Data). + Key + end, Data). diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl index 1244d60..fdd8a38 100644 --- a/src/ec_orddict.erl +++ b/src/ec_orddict.erl @@ -48,59 +48,59 @@ has_key(Key, Data) -> orddict:is_key(Key, Data). -spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> - ec_dictionary:value(V). + ec_dictionary:value(V). get(Key, Data) -> case orddict:find(Key, Data) of {ok, Value} -> Value; - error -> + error -> throw(not_found) end. -spec get(ec_dictionary:key(K), Default::ec_dictionary:value(V), Object::dictionary(K, V)) -> - ec_dictionary:value(V). + ec_dictionary:value(V). get(Key, Default, Data) -> case orddict:find(Key, Data) of {ok, Value} -> Value; - error -> + error -> Default end. -spec add(ec_dictionary:key(K), ec_dictionary:value(V), Object::dictionary(K, V)) -> - dictionary(K, V). + dictionary(K, V). add(Key, Value, Data) -> orddict:store(Key, Value, Data). -spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> - dictionary(K, V). + dictionary(K, V). remove(Key, Data) -> orddict:erase(Key, Data). -spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). has_value(Value, Data) -> orddict:fold(fun(_, NValue, _) when NValue == Value -> - true; - (_, _, Acc) -> - Acc - end, - false, - Data). + true; + (_, _, Acc) -> + Acc + end, + false, + Data). -spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). size(Data) -> orddict:size(Data). -spec to_list(dictionary(K, V)) -> - [{ec_dictionary:key(K), ec_dictionary:value(V)}]. + [{ec_dictionary:key(K), ec_dictionary:value(V)}]. to_list(Data) -> orddict:to_list(Data). -spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). + dictionary(K, V). from_list(List) when is_list(List) -> orddict:from_list(List). diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl index 1bfcecc..f28f625 100644 --- a/src/ec_rbdict.erl +++ b/src/ec_rbdict.erl @@ -139,12 +139,12 @@ size(T) -> size1(T). -spec to_list(dictionary(K, V)) -> - [{ec_dictionary:key(K), ec_dictionary:value(V)}]. + [{ec_dictionary:key(K), ec_dictionary:value(V)}]. to_list(T) -> to_list(T, []). -spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). + dictionary(K, V). from_list(L) -> lists:foldl(fun ({K, V}, D) -> add(K, V, D) @@ -159,7 +159,7 @@ keys(Dict) -> %%% Enternal functions %%%=================================================================== -spec keys(dictionary(K, _V), [ec_dictionary:key(K)]) -> - [ec_dictionary:key(K)]. + [ec_dictionary:key(K)]. keys(empty, Tail) -> Tail; keys({_, L, K, _, R}, Tail) -> @@ -167,7 +167,7 @@ keys({_, L, K, _, R}, Tail) -> -spec erase_aux(ec_dictionary:key(K), dictionary(K, V)) -> - {dictionary(K, V), boolean()}. + {dictionary(K, V), boolean()}. erase_aux(_, empty) -> {empty, false}; erase_aux(K, {b, A, Xk, Xv, B}) -> @@ -228,7 +228,7 @@ erase_aux(K, {r, A, Xk, Xv, B}) -> end. -spec erase_min(dictionary(K, V)) -> - {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean()}. + {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean()}. erase_min({b, empty, Xk, Xv, empty}) -> {empty, {Xk, Xv}, true}; erase_min({b, empty, Xk, Xv, {r, A, Yk, Yv, B}}) -> @@ -240,15 +240,15 @@ erase_min({r, empty, Xk, Xv, A}) -> erase_min({b, A, Xk, Xv, B}) -> {A1, Min, Dec} = erase_min(A), if Dec -> - {T, Dec1} = unbalright(b, A1, Xk, Xv, B), - {T, Min, Dec1}; + {T, Dec1} = unbalright(b, A1, Xk, Xv, B), + {T, Min, Dec1}; true -> {{b, A1, Xk, Xv, B}, Min, false} end; erase_min({r, A, Xk, Xv, B}) -> {A1, Min, Dec} = erase_min(A), if Dec -> - {T, Dec1} = unbalright(r, A1, Xk, Xv, B), - {T, Min, Dec1}; + {T, Dec1} = unbalright(r, A1, Xk, Xv, B), + {T, Min, Dec1}; true -> {{r, A1, Xk, Xv, B}, Min, false} end. @@ -299,7 +299,7 @@ to_list({_, A, Xk, Xv, B}, List) -> -spec lbalance(color(), dictionary(K, V), ec_dictionary:key(K), ec_dictionary:value(V), dictionary(K, V)) -> - dictionary(K, V). + dictionary(K, V). lbalance(b, {r, {r, A, Xk, Xv, B}, Yk, Yv, C}, Zk, Zv, D) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; @@ -311,7 +311,7 @@ lbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. -spec rbalance(color(), dictionary(K, V), ec_dictionary:key(K), ec_dictionary:value(V), dictionary(K, V)) -> - dictionary(K, V). + dictionary(K, V). rbalance(b, A, Xk, Xv, {r, {r, B, Yk, Yv, C}, Zk, Zv, D}) -> {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; From 9b9f070a5f4615b84645f9ba570f98a0251925a4 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Wed, 5 Sep 2012 17:01:11 -0500 Subject: [PATCH 029/240] move ec_file away from exceptions to return values In an attempt to unify on the accepted use of return values ec_file is changing its API to use return values instead of exceptions. Signed-off-by: Jordan Wilberding --- src/ec_file.erl | 134 ++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 83 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index cc40c07..c5cbe56 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -28,14 +28,6 @@ -include_lib("kernel/include/file.hrl"). -%% User friendly exception message (remove line and module info once we -%% get them in stack traces) --define(UEX(Exception, UMSG, UVARS), - {uex, {?MODULE, - ?LINE, - Exception, - lists:flatten(io_lib:fwrite(UMSG, UVARS))}}). - -define(CHECK_PERMS_MSG, "Try checking that you have the correct permissions and try again~n"). @@ -61,12 +53,23 @@ copy(From, To, [recursive] = Options) -> end. %% @doc copy a file including timestamps,ownership and mode etc. --spec copy(From::file:filename(), To::file:filename()) -> ok. +-spec copy(From::file:filename(), To::file:filename()) -> ok | {error, Reason::term()}. copy(From, To) -> - try - ec_file_copy(From, To) - catch - _C:E -> throw(?UEX({copy_failed, E}, ?CHECK_PERMS_MSG, [])) + case file:copy(From, To) of + {ok, _} -> + case file:read_file_info(From) of + {ok, FileInfo} -> + case file:write_file_info(To, FileInfo) of + ok -> + ok; + {error, WFError} -> + {error, {write_file_info_failed, WFError}} + end; + {error, RFError} -> + {error, {read_file_info_failed, RFError}} + end; + {error, Error} -> + {error, {copy_failed, Error}} end. %% @doc return an md5 checksum string or a binary. Same as unix utility of @@ -81,12 +84,12 @@ md5sum(Value) -> %% -spec remove(file:name(), Options::[option()]) -> ok | {error, Reason::term()}. remove(Path, Options) -> - try - ok = ec_file_remove(Path, Options) - catch - _C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, [])) + case lists:member(recursive, Options) of + false -> file:delete(Path); + true -> remove_recursive(Path, Options) end. + %% @doc delete a file. -spec remove(file:name()) -> ok | {error, Reason::term()}. remove(Path) -> @@ -112,32 +115,26 @@ insecure_mkdtemp() -> TmpDirPath = filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]), - case filelib:is_dir(TmpDirPath) of - true -> - throw(?UEX({mkdtemp_failed, file_exists}, "tmp directory exists", [])); - false -> - try - ok = mkdir_path(TmpDirPath), - TmpDirPath - catch - _C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, [])) - end + case mkdir_path(TmpDirPath) of + ok -> TmpDirPath; + Error -> Error end. - %% @doc Makes a directory including parent dirs if they are missing. --spec mkdir_path(file:name()) -> ok. -mkdir_path(Path) -> +-spec mkdir_p(file:name()) -> ok | {error, Reason::term()}. +mkdir_p(Path) -> %% We are exploiting a feature of ensuredir that that creates all %% directories up to the last element in the filename, then ignores %% that last element. This way we ensure that the dir is created %% and not have any worries about path names DirName = filename:join([filename:absname(Path), "tmp"]), - try - ok = filelib:ensure_dir(DirName) - catch - _C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, [])) - end. + filelib:ensure_dir(DirName). + + +%% @doc Makes a directory including parent dirs if they are missing. +-spec mkdir_path(file:name()) -> ok | {error, Reason::term()}. +mkdir_path(Path) -> + mkdir_p(Path). %% @doc consult an erlang term file from the file system. @@ -147,45 +144,28 @@ consult(FilePath) -> case file:consult(FilePath) of {ok, [Term]} -> Term; - {error, Error} -> - Msg = "The file at ~p~n" ++ - "is either not a valid Erlang term, does not to exist~n" ++ - "or you lack the permissions to read it. Please check~n" ++ - "to see if the file exists and that it has the correct~n" ++ - "permissions~n", - throw(?UEX({failed_to_consult_file, {FilePath, Error}}, - Msg, [FilePath])) + Error -> + Error end. - %% @doc read a file from the file system. Provide UEX exeption on failure. --spec read(FilePath::file:filename()) -> binary(). +-spec read(FilePath::file:filename()) -> binary() | {error, Reason::term()}. read(FilePath) -> - try - {ok, FileBin} = file:read_file(FilePath), - FileBin - catch - _C:E -> throw(?UEX({read_failed, {FilePath, E}}, - "Read failed for the file ~p with ~p~n" ++ - ?CHECK_PERMS_MSG, - [FilePath, E])) - end. + %% Now that we are moving away from exceptions again this becomes + %% a bit redundant but we want to be backwards compatible as much + %% as possible in the api. + file:read_file(FilePath). + %% @doc write a file to the file system. Provide UEX exeption on failure. --spec write(FileName::file:filename(), Contents::string()) -> ok. +-spec write(FileName::file:filename(), Contents::string()) -> ok | {error, Reason::term()}. write(FileName, Contents) -> - case file:write_file(FileName, Contents) of - ok -> - ok; - {error, Reason} -> - Msg = "Writing the file ~s to disk failed with reason ~p.~n" ++ - ?CHECK_PERMS_MSG, - throw(?UEX({write_file_failure, {FileName, Reason}}, - Msg, - [FileName, Reason])) - end. + %% Now that we are moving away from exceptions again this becomes + %% a bit redundant but we want to be backwards compatible as much + %% as possible in the api. + file:write_file(FileName, Contents). %% @doc write a term out to a file so that it can be consulted later. --spec write_term(file:filename(), term()) -> ok. +-spec write_term(file:filename(), term()) -> ok | {error, Reason::term()}. write_term(FileName, Term) -> write(FileName, lists:flatten(io_lib:fwrite("~p. ", [Term]))). @@ -226,14 +206,8 @@ find_in_subdirs(FromDir, TargetPattern) -> [], filelib:wildcard(filename:join(FromDir, "*"))). --spec ec_file_remove(file:name(), [option()]) -> ok | {error, Reason::any()}. -ec_file_remove(Path, Options) -> - case lists:member(recursive, Options) of - false -> file:delete(Path); - true -> remove_recursive(Path, Options) - end. --spec remove_recursive(file:name(), Options::list()) -> ok. +-spec remove_recursive(file:name(), Options::list()) -> ok | {error, Reason::term()}. remove_recursive(Path, Options) -> case filelib:is_dir(Path) of false -> @@ -242,7 +216,7 @@ remove_recursive(Path, Options) -> lists:foreach(fun(ChildPath) -> remove_recursive(ChildPath, Options) end, filelib:wildcard(filename:join(Path, "*"))), - ok = file:del_dir(Path) + file:del_dir(Path) end. -spec tmp() -> file:name(). @@ -264,17 +238,11 @@ copy_subfiles(From, To, Options) -> end, lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). --spec ec_file_copy(file:name(), file:name()) -> ok. -ec_file_copy(From, To) -> - {ok, _} = file:copy(From, To), - {ok, FileInfo} = file:read_file_info(From), - ok = file:write_file_info(To, FileInfo). - --spec make_dir_if_dir(file:name()) -> ok. +-spec make_dir_if_dir(file:name()) -> ok | {error, Reason::term()}. make_dir_if_dir(File) -> case filelib:is_dir(File) of true -> ok; - false -> ok = mkdir_path(File) + false -> mkdir_path(File) end. %% @doc convert a list of integers into hex. @@ -318,7 +286,7 @@ file_test() -> filelib:ensure_dir(TermFileCopy), write_term(TermFile, "term"), ?assertMatch("term", consult(TermFile)), - ?assertMatch(<<"\"term\". ">>, read(TermFile)), + ?assertMatch({ok, <<"\"term\". ">>}, read(TermFile)), copy(filename:dirname(TermFile), filename:dirname(TermFileCopy), [recursive]), From bf37ad94921caec8692e111b3c1f94fb85273ee7 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Wed, 5 Sep 2012 17:27:29 -0500 Subject: [PATCH 030/240] suport proper semver parsing and comparison in the semver module Signed-off-by: Jordan Wilberding --- .gitignore | 1 + rebar.config | 6 +- src/ec_semver.erl | 567 ++++++++++++++++++++++++++++++------ src/ec_semver_parser.peg | 13 + src/erlware_commons.app.src | 15 +- 5 files changed, 504 insertions(+), 98 deletions(-) create mode 100644 src/ec_semver_parser.peg diff --git a/.gitignore b/.gitignore index 65c6b5c..443f45b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ ebin/* _build erl_crash.dump *.pyc +src/ec_semver_parser.erl diff --git a/rebar.config b/rebar.config index ded76c0..6284cba 100644 --- a/rebar.config +++ b/rebar.config @@ -1,9 +1,9 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- %% These are all only compile time dependencies -{deps, [ - {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}} - ]}. +{deps, [{neotoma, "", + {git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5"}}}, + {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}]}. {erl_first_files, ["ec_dictionary"]}. diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 49a16a9..4dc83e9 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -7,95 +7,213 @@ %%%------------------------------------------------------------------- -module(ec_semver). --exports([ - compare/2 - ]). +-export([parse/1, + eql/2, + gt/2, + gte/2, + lt/2, + lte/2, + pes/2, + between/3]). --export_type([ - semvar/0 - ]). +%% For internal use by the ec_semver_parser peg +-export([internal_parse_version/1]). + +-export_type([semver/0, + version_string/0, + any_version/0]). %%%=================================================================== %%% Public Types %%%=================================================================== --type semvar() :: string(). --type parsed_semvar() :: {MajorVsn::integer(), - MinorVsn::integer(), - PatchVsn::integer(), - PathString::string()}. +-type major_minor_patch() :: + non_neg_integer() + | {non_neg_integer(), non_neg_integer()} + | {non_neg_integer(), non_neg_integer(), non_neg_integer()}. --type semver_tokens() :: {string(), string(), string(), string()}. +-type alpha_part() :: integer() | binary(). + +-type semver() :: {major_minor_patch(), {PreReleaseVersion::[alpha_part()], + BuildVersion::[alpha_part()]}}. + +-type version_string() :: string() | binary(). + +-type any_version() :: version_string() | semver(). %%%=================================================================== %%% API %%%=================================================================== -%% @doc Is semver version string A bigger than version string B? -%%
-%% Example: compare("3.2.5alpha", "3.10.6") returns: false
-%% 
--spec compare(VsnA::string(), VsnB::string()) -> boolean(). -compare(VsnA, VsnB) -> - compare_toks(tokens(VsnA),tokens(VsnB)). +%% @doc parse a string or binary into a valid semver representation +-spec parse(any_version()) -> semver(). +parse(Version) when erlang:is_list(Version) -> + ec_semver_parser:parse(Version); +parse(Version) when erlang:is_binary(Version) -> + ec_semver_parser:parse(Version); +parse(Version) -> + Version. + +%% @doc test for quality between semver versions +-spec eql(any_version(), any_version()) -> boolean(). +eql(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + NVsnA =:= NVsnB. + +%% @doc Test that VsnA is greater than VsnB +-spec gt(any_version(), any_version()) -> boolean(). +gt(VsnA, VsnB) -> + {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), + {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), + ((MMPA > MMPB) + orelse + ((MMPA =:= MMPB) + andalso + ((AlphaA =:= [] andalso AlphaB =/= []) + orelse + ((not (AlphaB =:= [] andalso AlphaA =/= [])) + andalso + (AlphaA > AlphaB)))) + orelse + ((MMPA =:= MMPB) + andalso + (AlphaA =:= AlphaB) + andalso + ((PatchB =:= [] andalso PatchA =/= []) + orelse + PatchA > PatchB))). + +%% @doc Test that VsnA is greater than or equal to VsnB +-spec gte(any_version(), any_version()) -> boolean(). +gte(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + gt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). + +%% @doc Test that VsnA is less than VsnB +-spec lt(any_version(), any_version()) -> boolean(). +lt(VsnA, VsnB) -> + {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), + {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), + ((MMPA < MMPB) + orelse + ((MMPA =:= MMPB) + andalso + ((AlphaB =:= [] andalso AlphaA =/= []) + orelse + ((not (AlphaA =:= [] andalso AlphaB =/= [])) + andalso + (AlphaA < AlphaB)))) + orelse + ((MMPA =:= MMPB) + andalso + (AlphaA =:= AlphaB) + andalso + ((PatchA =:= [] andalso PatchB =/= []) + orelse + PatchA < PatchB))). + +%% @doc Test that VsnA is less than or equal to VsnB +-spec lte(any_version(), any_version()) -> boolean(). +lte(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + lt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). + +%% @doc Test that VsnMatch is greater than or equal to Vsn1 and +%% less than or equal to Vsn2 +-spec between(any_version(), any_version(), any_version()) -> boolean(). +between(Vsn1, Vsn2, VsnMatch) -> + NVsnA = normalize(parse(Vsn1)), + NVsnB = normalize(parse(Vsn2)), + NVsnMatch = normalize(parse(VsnMatch)), + gte(NVsnMatch, NVsnA) andalso + lte(NVsnMatch, NVsnB). + +%% @doc check that VsnA is Approximately greater than VsnB +%% +%% Specifying ">= 2.6.5" is an optimistic version constraint. All +%% versions greater than the one specified, including major releases +%% (e.g. 3.0.0) are allowed. +%% +%% Conversely, specifying "~> 2.6" is pessimistic about future major +%% revisions and "~> 2.6.5" is pessimistic about future minor +%% revisions. +%% +%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0 +%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0 +pes(VsnA, VsnB) -> + internal_pes(parse(VsnA), parse(VsnB)). + +%%%=================================================================== +%%% Friend Functions +%%%=================================================================== +%% @doc helper function for the peg grammer to parse the iolist into a semver +-spec internal_parse_version(iolist()) -> semver(). +internal_parse_version([MMP, AlphaPart, BuildPart, _]) -> + {parse_major_minor_patch(MMP), {parse_alpha_part(AlphaPart), + parse_alpha_part(BuildPart)}}. + +%% @doc helper function for the peg grammer to parse the iolist into a major_minor_patch +-spec parse_major_minor_patch(iolist()) -> major_minor_patch(). +parse_major_minor_patch([MajVsn, [], []]) -> + MajVsn; +parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], []]) -> + {MajVsn, MinVsn}; +parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn]]) -> + {MajVsn, MinVsn, PatchVsn}. + +%% @doc helper function for the peg grammer to parse the iolist into an alpha part +-spec parse_alpha_part(iolist()) -> [alpha_part()]. +parse_alpha_part([]) -> + []; +parse_alpha_part([_, AV1, Rest]) -> + [erlang:iolist_to_binary(AV1) | + [format_alpha_part(Part) || Part <- Rest]]. + +%% @doc according to semver alpha parts that can be treated like +%% numbers must be. We implement that here by taking the alpha part +%% and trying to convert it to a number, if it succeeds we use +%% it. Otherwise we do not. +-spec format_alpha_part(iolist()) -> integer() | binary(). +format_alpha_part([<<".">>, AlphaPart]) -> + Bin = erlang:iolist_to_binary(AlphaPart), + try + erlang:list_to_integer(erlang:binary_to_list(Bin)) + catch + error:badarg -> + Bin + end. %%%=================================================================== %%% Internal Functions %%%=================================================================== +%% @doc normalize the semver so they can be compared +-spec normalize(semver()) -> semver(). +normalize({Vsn, Rest}) + when erlang:is_integer(Vsn) -> + {{Vsn, 0, 0}, Rest}; +normalize({{Maj, Min}, Rest}) -> + {{Maj, Min, 0}, Rest}; +normalize(Other) -> + Other. --spec tokens(semvar()) -> semver_tokens(). -tokens(Vsn) -> - [MajorVsn, MinorVsn, RawPatch] = string:tokens(Vsn, "."), - {PatchVsn, PatchString} = split_patch(RawPatch), - {MajorVsn, MinorVsn, PatchVsn, PatchString}. +%% @doc to do the pessimistic compare we need a parsed semver. This is +%% the internal implementation of the of the pessimistic run. The +%% external just ensures that versions are parsed. +internal_pes(VsnA, {{LM, LMI}, _}) -> + gte(VsnA, {{LM, LMI, 0}, {[], []}}) andalso + lt(VsnA, {{LM + 1, 0, 0}, {[], []}}); +internal_pes(VsnA, {{LM, LMI, LP}, _}) -> + gte(VsnA, {{LM, LMI, LP}, {[], []}}) + andalso + lt(VsnA, {{LM, LMI + 1, 0}, {[], []}}); +internal_pes(Vsn, LVsn) -> + gte(Vsn, LVsn). --spec split_patch(string()) -> - {PatchVsn::string(), PatchStr::string()}. -split_patch(RawPatch) -> - {PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}), - {lists:reverse(PatchVsn), PatchStr}. --spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) -> - {PatchVsn::string(), PatchStr::string()}. -split_patch([], Acc) -> - Acc; -split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> - split_patch(T, {[Dig|PatchVsn], PatchStr}); -split_patch(PatchStr, {PatchVsn, ""}) -> - {PatchVsn, PatchStr}. --spec compare_toks(semver_tokens(), semver_tokens()) -> boolean(). -compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) -> - compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA}, - {to_int(MajB), to_int(MinB), to_int(PVB), PSB}). - --spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean(). -compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB}) - when MajA > MajB -> - true; -compare_toks2({_Maj, MinA, _PVA, _PSA}, {_Maj, MinB, _PVB, _PSB}) - when MinA > MinB -> - true; -compare_toks2({_Maj, _Min, PVA, _PSA}, {_Maj, _Min, PVB, _PSB}) - when PVA > PVB -> - true; -compare_toks2({_Maj, _Min, _PV, ""}, {_Maj, _Min, _PV, PSB}) when PSB /= ""-> - true; -compare_toks2({_Maj, _Min, _PV, PSA}, {_Maj, _Min, _PV, ""}) when PSA /= ""-> - false; -compare_toks2({_Maj, _Min, _PV, PSA}, {_Maj, _Min, _PV, PSB}) when PSA > PSB -> - true; -compare_toks2(_ToksA, _ToksB) -> - false. - --spec to_int(string()) -> integer(). -to_int(String) -> - try - list_to_integer(String) - catch - error:badarg -> - throw(invalid_semver_string) - end. %%%=================================================================== %%% Test Functions @@ -104,18 +222,305 @@ to_int(String) -> -ifndef(NOTEST). -include_lib("eunit/include/eunit.hrl"). -split_patch_test() -> - ?assertMatch({"123", "alpha1"}, split_patch("123alpha1")). +eql_test() -> + ?assertMatch(true, eql("1.0.0-alpha", + "1.0.0-alpha")), + ?assertMatch(true, eql("1", + "1.0.0")), + ?assertMatch(true, eql("1.0", + "1.0.0")), + ?assertMatch(true, eql("1.0.0", + "1")), + ?assertMatch(true, eql("1.0+alpha.1", + "1.0.0+alpha.1")), + ?assertMatch(true, eql("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")), + ?assertMatch(true, not eql("1.0.0", + "1.0.1")), + ?assertMatch(true, not eql("1.0.0-alpha", + "1.0.1+alpha")), + ?assertMatch(true, not eql("1.0.0+build.1", + "1.0.1+build.2")). -compare_test() -> - ?assertMatch(true, compare("1.2.3", "1.2.3alpha")), - ?assertMatch(true, compare("1.2.3beta", "1.2.3alpha")), - ?assertMatch(true, compare("1.2.4", "1.2.3")), - ?assertMatch(true, compare("1.3.3", "1.2.3")), - ?assertMatch(true, compare("2.2.3", "1.2.3")), - ?assertMatch(true, compare("4.2.3", "3.10.3")), - ?assertMatch(false, compare("1.2.3", "2.2.3")), - ?assertThrow(invalid_semver_string, compare("1.b.2", "1.3.4")), - ?assertThrow(invalid_semver_string, compare("1.2.2", "1.3.t")). + +gt_test() -> + ?assertMatch(true, gt("1.0.0-alpha.1", + "1.0.0-alpha")), + ?assertMatch(true, gt("1.0.0-beta.2", + "1.0.0-alpha.1")), + ?assertMatch(true, gt("1.0.0-beta.11", + "1.0.0-beta.2")), + ?assertMatch(true, gt("1.0.0-rc.1", "1.0.0-beta.11")), + ?assertMatch(true, gt("1.0.0-rc.1+build.1", "1.0.0-rc.1")), + ?assertMatch(true, gt("1.0.0", "1.0.0-rc.1+build.1")), + ?assertMatch(true, gt("1.0.0+0.3.7", "1.0.0")), + ?assertMatch(true, gt("1.3.7+build", "1.0.0+0.3.7")), + ?assertMatch(true, gt("1.3.7+build.2.b8f12d7", + "1.3.7+build")), + ?assertMatch(true, gt("1.3.7+build.11.e0f985a", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, not gt("1.0.0-alpha", + "1.0.0-alpha.1")), + ?assertMatch(true, not gt("1.0.0-alpha.1", + "1.0.0-beta.2")), + ?assertMatch(true, not gt("1.0.0-beta.2", + "1.0.0-beta.11")), + ?assertMatch(true, not gt("1.0.0-beta.11", + "1.0.0-rc.1")), + ?assertMatch(true, not gt("1.0.0-rc.1", + "1.0.0-rc.1+build.1")), + ?assertMatch(true, not gt("1.0.0-rc.1+build.1", + "1.0.0")), + ?assertMatch(true, not gt("1.0.0", + "1.0.0+0.3.7")), + ?assertMatch(true, not gt("1.0.0+0.3.7", + "1.3.7+build")), + ?assertMatch(true, not gt("1.3.7+build", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, not gt("1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a")), + ?assertMatch(true, not gt("1.0.0-alpha", + "1.0.0-alpha")), + ?assertMatch(true, not gt("1", + "1.0.0")), + ?assertMatch(true, not gt("1.0", + "1.0.0")), + ?assertMatch(true, not gt("1.0.0", + "1")), + ?assertMatch(true, not gt("1.0+alpha.1", + "1.0.0+alpha.1")), + ?assertMatch(true, not gt("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")). + +lt_test() -> + ?assertMatch(true, lt("1.0.0-alpha", + "1.0.0-alpha.1")), + ?assertMatch(true, lt("1.0.0-alpha.1", + "1.0.0-beta.2")), + ?assertMatch(true, lt("1.0.0-beta.2", + "1.0.0-beta.11")), + ?assertMatch(true, lt("1.0.0-beta.11", + "1.0.0-rc.1")), + ?assertMatch(true, lt("1.0.0-rc.1", + "1.0.0-rc.1+build.1")), + ?assertMatch(true, lt("1.0.0-rc.1+build.1", + "1.0.0")), + ?assertMatch(true, lt("1.0.0", + "1.0.0+0.3.7")), + ?assertMatch(true, lt("1.0.0+0.3.7", + "1.3.7+build")), + ?assertMatch(true, lt("1.3.7+build", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, lt("1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a")), + ?assertMatch(true, not lt("1.0.0-alpha", + "1.0.0-alpha")), + ?assertMatch(true, not lt("1", + "1.0.0")), + ?assertMatch(true, not lt("1.0", + "1.0.0")), + ?assertMatch(true, not lt("1.0.0", + "1")), + ?assertMatch(true, not lt("1.0+alpha.1", + "1.0.0+alpha.1")), + ?assertMatch(true, not lt("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")), + ?assertMatch(true, not lt("1.0.0-alpha.1", + "1.0.0-alpha")), + ?assertMatch(true, not lt("1.0.0-beta.2", + "1.0.0-alpha.1")), + ?assertMatch(true, not lt("1.0.0-beta.11", + "1.0.0-beta.2")), + ?assertMatch(true, not lt("1.0.0-rc.1", "1.0.0-beta.11")), + ?assertMatch(true, not lt("1.0.0-rc.1+build.1", "1.0.0-rc.1")), + ?assertMatch(true, not lt("1.0.0", "1.0.0-rc.1+build.1")), + ?assertMatch(true, not lt("1.0.0+0.3.7", "1.0.0")), + ?assertMatch(true, not lt("1.3.7+build", "1.0.0+0.3.7")), + ?assertMatch(true, not lt("1.3.7+build.2.b8f12d7", + "1.3.7+build")), + ?assertMatch(true, not lt("1.3.7+build.11.e0f985a", + "1.3.7+build.2.b8f12d7")). + + +gte_test() -> + ?assertMatch(true, gte("1.0.0-alpha", + "1.0.0-alpha")), + + ?assertMatch(true, gte("1", + "1.0.0")), + + ?assertMatch(true, gte("1.0", + "1.0.0")), + + ?assertMatch(true, gte("1.0.0", + "1")), + + ?assertMatch(true, gte("1.0+alpha.1", + "1.0.0+alpha.1")), + + ?assertMatch(true, gte("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")), + + ?assertMatch(true, gte("1.0.0-alpha.1", + "1.0.0-alpha")), + ?assertMatch(true, gte("1.0.0-beta.2", + "1.0.0-alpha.1")), + ?assertMatch(true, gte("1.0.0-beta.11", + "1.0.0-beta.2")), + ?assertMatch(true, gte("1.0.0-rc.1", "1.0.0-beta.11")), + ?assertMatch(true, gte("1.0.0-rc.1+build.1", "1.0.0-rc.1")), + ?assertMatch(true, gte("1.0.0", "1.0.0-rc.1+build.1")), + ?assertMatch(true, gte("1.0.0+0.3.7", "1.0.0")), + ?assertMatch(true, gte("1.3.7+build", "1.0.0+0.3.7")), + ?assertMatch(true, gte("1.3.7+build.2.b8f12d7", + "1.3.7+build")), + ?assertMatch(true, gte("1.3.7+build.11.e0f985a", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, not gte("1.0.0-alpha", + "1.0.0-alpha.1")), + ?assertMatch(true, not gte("1.0.0-alpha.1", + "1.0.0-beta.2")), + ?assertMatch(true, not gte("1.0.0-beta.2", + "1.0.0-beta.11")), + ?assertMatch(true, not gte("1.0.0-beta.11", + "1.0.0-rc.1")), + ?assertMatch(true, not gte("1.0.0-rc.1", + "1.0.0-rc.1+build.1")), + ?assertMatch(true, not gte("1.0.0-rc.1+build.1", + "1.0.0")), + ?assertMatch(true, not gte("1.0.0", + "1.0.0+0.3.7")), + ?assertMatch(true, not gte("1.0.0+0.3.7", + "1.3.7+build")), + ?assertMatch(true, not gte("1.0.0", + "1.0.0+build.1")), + ?assertMatch(true, not gte("1.3.7+build", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, not gte("1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a")). +lte_test() -> + ?assertMatch(true, lte("1.0.0-alpha", + "1.0.0-alpha.1")), + ?assertMatch(true, lte("1.0.0-alpha.1", + "1.0.0-beta.2")), + ?assertMatch(true, lte("1.0.0-beta.2", + "1.0.0-beta.11")), + ?assertMatch(true, lte("1.0.0-beta.11", + "1.0.0-rc.1")), + ?assertMatch(true, lte("1.0.0-rc.1", + "1.0.0-rc.1+build.1")), + ?assertMatch(true, lte("1.0.0-rc.1+build.1", + "1.0.0")), + ?assertMatch(true, lte("1.0.0", + "1.0.0+0.3.7")), + ?assertMatch(true, lte("1.0.0+0.3.7", + "1.3.7+build")), + ?assertMatch(true, lte("1.3.7+build", + "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, lte("1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a")), + ?assertMatch(true, lte("1.0.0-alpha", + "1.0.0-alpha")), + ?assertMatch(true, lte("1", + "1.0.0")), + ?assertMatch(true, lte("1.0", + "1.0.0")), + ?assertMatch(true, lte("1.0.0", + "1")), + ?assertMatch(true, lte("1.0+alpha.1", + "1.0.0+alpha.1")), + ?assertMatch(true, lte("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")), + ?assertMatch(true, not lt("1.0.0-alpha.1", + "1.0.0-alpha")), + ?assertMatch(true, not lt("1.0.0-beta.2", + "1.0.0-alpha.1")), + ?assertMatch(true, not lt("1.0.0-beta.11", + "1.0.0-beta.2")), + ?assertMatch(true, not lt("1.0.0-rc.1", "1.0.0-beta.11")), + ?assertMatch(true, not lt("1.0.0-rc.1+build.1", "1.0.0-rc.1")), + ?assertMatch(true, not lt("1.0.0", "1.0.0-rc.1+build.1")), + ?assertMatch(true, not lt("1.0.0+0.3.7", "1.0.0")), + ?assertMatch(true, not lt("1.3.7+build", "1.0.0+0.3.7")), + ?assertMatch(true, not lt("1.3.7+build.2.b8f12d7", + "1.3.7+build")), + ?assertMatch(true, not lt("1.3.7+build.11.e0f985a", + "1.3.7+build.2.b8f12d7")). + + +between_test() -> + ?assertMatch(true, between("1.0.0-alpha", + "1.0.0-alpha.3", + "1.0.0-alpha.2")), + ?assertMatch(true, between("1.0.0-alpha.1", + "1.0.0-beta.2", + "1.0.0-alpha.25")), + ?assertMatch(true, between("1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-beta.7")), + ?assertMatch(true, between("1.0.0-beta.11", + "1.0.0-rc.3", + "1.0.0-rc.1")), + ?assertMatch(true, between("1.0.0-rc.1", + "1.0.0-rc.1+build.3", + "1.0.0-rc.1+build.1")), + ?assertMatch(true, between("1.0.0-rc.1+build.1", + "1.0.0", + "1.0.0-rc.33")), + ?assertMatch(true, between("1.0.0", + "1.0.0+0.3.7", + "1.0.0+0.2")), + ?assertMatch(true, between("1.0.0+0.3.7", + "1.3.7+build", + "1.2")), + ?assertMatch(true, between("1.3.7+build", + "1.3.7+build.2.b8f12d7", + "1.3.7+build.1")), + ?assertMatch(true, between("1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a", + "1.3.7+build.10.a36faa")), + ?assertMatch(true, between("1.0.0-alpha", + "1.0.0-alpha", + "1.0.0-alpha")), + ?assertMatch(true, between("1", + "1.0.0", + "1.0.0")), + ?assertMatch(true, between("1.0", + "1.0.0", + "1.0.0")), + ?assertMatch(true, between("1.0.0", + "1", + "1")), + ?assertMatch(true, between("1.0+alpha.1", + "1.0.0+alpha.1", + "1.0.0+alpha.1")), + ?assertMatch(true, between("1.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1", + "1.0.0-alpha.1+build.1")), + ?assertMatch(true, not between("1.0.0-alpha.1", + "1.0.0-alpha.22", + "1.0.0")), + ?assertMatch(true, not between("1.0.0", + "1.0.0-alpha.1", + "2.0")), + ?assertMatch(true, not between("1.0.0-beta.1", + "1.0.0-beta.11", + "1.0.0-alpha")), + ?assertMatch(true, not between("1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.22")). + +pes_test() -> + ?assertMatch(true, pes("2.6.0", "2.6")), + ?assertMatch(true, pes("2.7", "2.6")), + ?assertMatch(true, pes("2.8", "2.6")), + ?assertMatch(true, pes("2.9", "2.6")), + ?assertMatch(true, not pes("3.0.0", "2.6")), + ?assertMatch(true, not pes("2.5", "2.6")), + ?assertMatch(true, pes("2.6.5", "2.6.5")), + ?assertMatch(true, pes("2.6.6", "2.6.5")), + ?assertMatch(true, pes("2.6.7", "2.6.5")), + ?assertMatch(true, pes("2.6.8", "2.6.5")), + ?assertMatch(true, pes("2.6.9", "2.6.5")), + ?assertMatch(true, not pes("2.7", "2.6.5")), + ?assertMatch(true, not pes("2.5", "2.6.5")). -endif. diff --git a/src/ec_semver_parser.peg b/src/ec_semver_parser.peg new file mode 100644 index 0000000..9636d95 --- /dev/null +++ b/src/ec_semver_parser.peg @@ -0,0 +1,13 @@ +semver <- major_minor_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !. + ` ec_semver:internal_parse_version(Node) ` ; + +major_minor_patch <- version_part ("." version_part)? ("." version_part)? ; + +version_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ; + +alpha_part <- [A-Za-z0-9-]+ ; + +%% This only exists to get around a bug in erlang where if +%% warnings_as_errors is specified `nowarn` directives are ignored + + `-compile(export_all).` \ No newline at end of file diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index a10e939..8a46f9c 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -2,19 +2,6 @@ {application, erlware_commons, [{description, "Additional standard library for Erlang"}, {vsn, "0.7.0"}, - {modules, [ - ec_talk, - ec_lists, - ec_plists, - ec_file, - ec_string, - ec_semver, - ec_date, - ec_dictionary, - ec_assoc_list, - ec_dict, - ec_gb_trees, - ec_rbdict, - ec_orddict]}, + {modules, []}, {registered, []}, {applications, [kernel, stdlib]}]}. From 4db670c812a46b14c70c7457e6db0fc9f33ad982 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Wed, 5 Sep 2012 17:07:22 -0500 Subject: [PATCH 031/240] given a complete semver parser ec_string no longer makes sense to retain It was really poorly named in any case Signed-off-by: Jordan Wilberding --- src/ec_string.erl | 128 ---------------------------------------------- 1 file changed, 128 deletions(-) delete mode 100644 src/ec_string.erl diff --git a/src/ec_string.erl b/src/ec_string.erl deleted file mode 100644 index 2a06257..0000000 --- a/src/ec_string.erl +++ /dev/null @@ -1,128 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @copyright (C) 2011, Erlware LLC -%%% @doc -%%% Helper functions for working with strings. -%%% @end -%%%------------------------------------------------------------------- --module(ec_string). - --export([ - compare_versions/2 - ]). -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc Is arbitrary version string A bigger than version string B? -%% Valid version string elements are either separated by . or - or both. -%% Final version string elements may have a numeric followed directly by an -%% alpha numeric and will be compared separately as in 12alpha. -%% -%%
-%% Example: compare_versions("3-2-5-alpha", "3.10.6") will return false
-%%          compare_versions("3-2-alpha", "3.2.1-alpha") will return false
-%%          compare_versions("3-2alpha", "3.2.1-alpha") will return false
-%%          compare_versions("3.2.2", "3.2.2") will return false
-%%          compare_versions("3.2.1", "3.2.1-rc2") will return true
-%%          compare_versions("3.2.2", "3.2.1") will return true
-%% 
--spec compare_versions(VsnA::string(), VsnB::string()) -> boolean(). -compare_versions(VsnA, VsnB) -> - compare(string:tokens(VsnA, ".-"),string:tokens(VsnB, ".-")). - -%%%=================================================================== -%%% Internal Functions -%%%=================================================================== - --spec compare(string(), string()) -> boolean(). -compare([Str|TA], [Str|TB]) -> - compare(TA, TB); -compare([StrA|TA], [StrB|TB]) -> - fine_compare(split_numeric_alpha(StrA), TA, - split_numeric_alpha(StrB), TB); -compare([], [Str]) -> - not compare_against_nothing(Str); -compare([Str], []) -> - compare_against_nothing(Str); -compare([], [_,_|_]) -> - false; -compare([_,_|_], []) -> - true; -compare([], []) -> - false. - --spec compare_against_nothing(string()) -> boolean(). -compare_against_nothing(Str) -> - case split_numeric_alpha(Str) of - {_StrDig, ""} -> true; - {"", _StrAlpha} -> false; - {_StrDig, _StrAlpha} -> true - end. - --spec fine_compare({string(), string()}, string(), - {string(), string()}, string()) -> - boolean(). -fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB) - when StrA /= "", TA /= [] -> - throw(invalid_version_string); -fine_compare({_StrDigA, _StrA}, _TA, {_StrDigB, StrB}, TB) - when StrB /= "", TB /= [] -> - throw(invalid_version_string); -fine_compare({"", _StrA}, _TA, {StrDigB, _StrB}, _TB) when StrDigB /= "" -> - false; -fine_compare({StrDigA, _StrA}, _TA, {"", _StrB}, _TB) when StrDigA /= "" -> - true; -fine_compare({StrDig, ""}, _TA, {StrDig, StrB}, _TB) when StrB /= "" -> - true; -fine_compare({StrDig, StrA}, _TA, {StrDig, ""}, _TB) when StrA /= "" -> - false; -fine_compare({StrDig, StrA}, _TA, {StrDig, StrB}, _TB) -> - StrA > StrB; -fine_compare({StrDigA, _StrA}, _TA, {StrDigB, _StrB}, _TB) -> - list_to_integer(StrDigA) > list_to_integer(StrDigB). - -%% In the case of a version sub part with a numeric then an alpha, -%% split out the numeric and alpha "24alpha" becomes {"24", "alpha"} --spec split_numeric_alpha(string()) -> - {PatchVsn::string(), PatchStr::string()}. -split_numeric_alpha(RawVsn) -> - {Num, Str} = split_numeric_alpha(RawVsn, {"", ""}), - {lists:reverse(Num), Str}. - --spec split_numeric_alpha(string(), {PatchVsnAcc::string(), - PatchStrAcc::string()}) -> - {PatchVsn::string(), PatchStr::string()}. -split_numeric_alpha([], Acc) -> - Acc; -split_numeric_alpha([Dig|T], {PatchVsn, PatchStr}) - when Dig >= $0 andalso Dig =< $9 -> - split_numeric_alpha(T, {[Dig|PatchVsn], PatchStr}); -split_numeric_alpha(PatchStr, {PatchVsn, ""}) -> - {PatchVsn, PatchStr}. - -%%%=================================================================== -%%% Test Functions -%%%=================================================================== - --ifndef(NOTEST). --include_lib("eunit/include/eunit.hrl"). - -split_numeric_alpha_test() -> - ?assertMatch({"123", "alpha1"}, split_numeric_alpha("123alpha1")). - -compare_versions_test() -> - ?assertMatch(true, compare_versions("1.2.3", "1.2.3alpha")), - ?assertMatch(true, compare_versions("1.2.3-beta", "1.2.3-alpha")), - ?assertMatch(true, compare_versions("1-2-3", "1-2-3alpha")), - ?assertMatch(true, compare_versions("1-2-3", "1-2-3-rc3")), - ?assertMatch(true, compare_versions("1.2.3beta", "1.2.3alpha")), - ?assertMatch(true, compare_versions("1.2.4", "1.2.3")), - ?assertMatch(true, compare_versions("1.3.3", "1.2.3")), - ?assertMatch(true, compare_versions("2.2.3", "1.2.3")), - ?assertMatch(true, compare_versions("4.2.3", "3.10.3")), - ?assertMatch(false, compare_versions("1.2.3", "2.2.3")), - ?assertMatch(false, compare_versions("1.2.2", "1.3.t")), - ?assertMatch(false, compare_versions("1.2t", "1.3.t")), - ?assertThrow(invalid_version_string, compare_versions("1.b.2", "1.3.4")). - --endif. From 67acaaaf3fabdf9518363199d96d37fe53a09331 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sat, 8 Sep 2012 09:02:12 -0500 Subject: [PATCH 032/240] minor fixes and enhancements to the makefile Signed-off-by: Jordan Wilberding --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d32718a..933ce28 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,9 @@ endif ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt -.PHONY: all compile doc clean eunit dialyzer typer shell distclean pdf get-deps escript +.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript -all: compile eunit dialyzer +all: compile test dialyzer get-deps: $(REBAR) get-deps @@ -28,7 +28,7 @@ compile: doc: compile $(REBAR) skip_deps=true doc -eunit: compile +test: compile $(REBAR) skip_deps=true eunit $(ERLWARE_COMMONS_PLT): @@ -53,11 +53,11 @@ shell: compile @$(ERL) $(ERLFLAGS) clean: - $(REBAR) clean - rm $(CURDIR)/doc/*.html - rm $(CURDIR)/doc/*.css - rm $(CURDIR)/doc/*.png - rm $(CURDIR)/doc/edoc-info + $(REBAR) skip_deps=true clean + - rm $(CURDIR)/doc/*.html + - rm $(CURDIR)/doc/*.css + - rm $(CURDIR)/doc/*.png + - rm $(CURDIR)/doc/edoc-info distclean: clean rm -rf $(ERLWARE_COMMONS_PLT) From c42581887aff4f7bb8599b7a82d294cdf6a91b5d Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Wed, 5 Sep 2012 17:10:45 -0500 Subject: [PATCH 033/240] version bump 0.8.0 Signed-off-by: Jordan Wilberding --- src/erlware_commons.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index 8a46f9c..8aaa5f3 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.7.0"}, + {vsn, "0.8.0"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib]}]}. From 1b0138061361d0d9cb3708141f5c1347e2e48bc8 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sun, 16 Sep 2012 13:11:41 -0500 Subject: [PATCH 034/240] compilation utilities for the implementors Signed-off-by: Jordan Wilberding --- src/ec_compile.erl | 107 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/ec_compile.erl diff --git a/src/ec_compile.erl b/src/ec_compile.erl new file mode 100644 index 0000000..482bdb3 --- /dev/null +++ b/src/ec_compile.erl @@ -0,0 +1,107 @@ +%%%------------------------------------------------------------------- +%%% @author Eric Merritt <> +%%% @copyright (C) 2011, Erlware, LLC. +%%% @doc +%%% These are various utility functions to help with compiling and +%%% decompiling erlang source. They are mostly useful to the +%%% language/parse transform implementor. +%%% @end +%%%------------------------------------------------------------------- +-module(ec_compile). + +-export([beam_to_erl_source/2, + erl_source_to_core_ast/1, + erl_source_to_erl_ast/1, + erl_source_to_asm/1, + erl_string_to_core_ast/1, + erl_string_to_erl_ast/1, + erl_string_to_asm/1]). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc decompile a beam file that has been compiled with +debug_info +%% into a erlang source file +%% +%% @param BeamFName the name of the beamfile +%% @param ErlFName the name of the erlang file where the generated +%% source file will be output. This should *not* be the same as the +%% source file that created the beamfile unless you want to overwrite +%% it. +-spec beam_to_erl_source(string(), string()) -> ok | term(). +beam_to_erl_source(BeamFName, ErlFName) -> + case beam_lib:chunks(BeamFName, [abstract_code]) of + {ok, {_, [{abstract_code, {raw_abstract_v1,Forms}}]}} -> + Src = + erl_prettypr:format(erl_syntax:form_list(tl(Forms))), + {ok, Fd} = file:open(ErlFName, [write]), + io:fwrite(Fd, "~s~n", [Src]), + file:close(Fd); + Error -> + Error + end. + +%% @doc compile an erlang source file into a Core Erlang AST +%% +%% @param Path - The path to the erlang source file +-spec erl_source_to_core_ast(file:filename()) -> CoreAst::term(). +erl_source_to_core_ast(Path) -> + {ok, Contents} = file:read_file(Path), + erl_string_to_core_ast(binary_to_list(Contents)). + +%% @doc compile an erlang source file into an Erlang AST +%% +%% @param Path - The path to the erlang source file +-spec erl_source_to_erl_ast(file:filename()) -> ErlangAst::term(). +erl_source_to_erl_ast(Path) -> + {ok, Contents} = file:read_file(Path), + erl_string_to_erl_ast(binary_to_list(Contents)). + +%% @doc compile an erlang source file into erlang terms that represent +%% the relevant ASM +%% +%% @param Path - The path to the erlang source file +-spec erl_source_to_asm(file:filename()) -> ErlangAsm::term(). +erl_source_to_asm(Path) -> + {ok, Contents} = file:read_file(Path), + erl_string_to_asm(binary_to_list(Contents)). + +%% @doc compile a string representing an erlang expression into an +%% Erlang AST +%% +%% @param StringExpr - The path to the erlang source file +-spec erl_string_to_erl_ast(string()) -> ErlangAst::term(). +erl_string_to_erl_ast(StringExpr) -> + Forms0 = + lists:foldl(fun(<<>>, Acc) -> + Acc; + (<<"\n\n">>, Acc) -> + Acc; + (El, Acc) -> + {ok, Tokens, _} = + erl_scan:string(binary_to_list(El) + ++ "."), + [Tokens | Acc] + end, [], re:split(StringExpr, "\\.\n")), + %% No need to reverse. This will rereverse for us + lists:foldl(fun(Form, Forms) -> + {ok, ErlAST} = erl_parse:parse_form(Form), + [ErlAST | Forms] + end, [], Forms0). + +%% @doc compile a string representing an erlang expression into a +%% Core Erlang AST +%% +%% @param StringExpr - The path to the erlang source file +-spec erl_string_to_core_ast(string()) -> CoreAst::term(). +erl_string_to_core_ast(StringExpr) -> + compile:forms(erl_string_to_erl_ast(StringExpr), [to_core]). + +%% @doc compile a string representing an erlang expression into a term +%% that represents the ASM +%% +%% @param StringExpr - The path to the erlang source file +-spec erl_string_to_asm(string()) -> ErlangAsm::term(). +erl_string_to_asm(StringExpr) -> + compile:forms(erl_string_to_erl_ast(StringExpr), ['S']). From 3a29539285786391fc5bef4230820651ba50e776 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 10 Sep 2012 18:21:58 -0500 Subject: [PATCH 035/240] fixes for edoc compilation Signed-off-by: Jordan Wilberding --- src/ec_semver.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 4dc83e9..cdff19e 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -141,8 +141,8 @@ between(Vsn1, Vsn2, VsnMatch) -> %% revisions and "~> 2.6.5" is pessimistic about future minor %% revisions. %% -%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0 -%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0 +%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0 +%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0 pes(VsnA, VsnB) -> internal_pes(parse(VsnA), parse(VsnB)). From 0c345499018398b1f3a0cecadad76a232c08f117 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 10 Sep 2012 18:23:56 -0500 Subject: [PATCH 036/240] make sure the docs get run as part of a bare make Signed-off-by: Jordan Wilberding --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 933ce28..538d561 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt .PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript -all: compile test dialyzer +all: compile test doc dialyzer get-deps: $(REBAR) get-deps From e9161d8688e7e2b902220c741ed584689243d899 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 18 Sep 2012 15:34:57 -0700 Subject: [PATCH 037/240] provide the ability to format a version into a string as well as parse a version Signed-off-by: Jordan Wilberding --- rebar.config | 2 +- src/ec_semver.erl | 54 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/rebar.config b/rebar.config index 6284cba..2c3cad3 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ %% These are all only compile time dependencies {deps, [{neotoma, "", - {git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5"}}}, + {git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5.1"}}}, {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}]}. {erl_first_files, ["ec_dictionary"]}. diff --git a/src/ec_semver.erl b/src/ec_semver.erl index cdff19e..83bf6ef 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -8,6 +8,7 @@ -module(ec_semver). -export([parse/1, + format/1, eql/2, gt/2, gte/2, @@ -32,10 +33,11 @@ | {non_neg_integer(), non_neg_integer()} | {non_neg_integer(), non_neg_integer(), non_neg_integer()}. --type alpha_part() :: integer() | binary(). +-type alpha_part() :: integer() | binary() | string(). +-type alpha_info() :: {PreRelease::[alpha_part()], + BuildVersion::[alpha_part()]}. --type semver() :: {major_minor_patch(), {PreReleaseVersion::[alpha_part()], - BuildVersion::[alpha_part()]}}. +-type semver() :: {major_minor_patch(), alpha_info()}. -type version_string() :: string() | binary(). @@ -54,6 +56,24 @@ parse(Version) when erlang:is_binary(Version) -> parse(Version) -> Version. +-spec format(semver()) -> iolist(). +format({Maj, {AlphaPart, BuildPart}}) + when erlang:is_integer(Maj) -> + [erlang:integer_to_list(Maj), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]; +format({{Maj, Min}, {AlphaPart, BuildPart}}) -> + [erlang:integer_to_list(Maj), ".", + erlang:integer_to_list(Min), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]; +format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) -> + [erlang:integer_to_list(Maj), ".", + erlang:integer_to_list(Min), ".", + erlang:integer_to_list(Patch), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]. + %% @doc test for quality between semver versions -spec eql(any_version(), any_version()) -> boolean(). eql(VsnA, VsnB) -> @@ -189,6 +209,19 @@ format_alpha_part([<<".">>, AlphaPart]) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec to_list(integer() | binary() | string()) -> string() | binary(). +to_list(Detail) when erlang:is_integer(Detail) -> + erlang:integer_to_list(Detail); +to_list(Detail) when erlang:is_list(Detail); erlang:is_binary(Detail) -> + Detail. + +-spec format_vsn_rest(binary() | string(), [integer() | binary()]) -> iolist(). +format_vsn_rest(_TypeMark, []) -> + []; +format_vsn_rest(TypeMark, [Head | Rest]) -> + [TypeMark, Head | + [[".", to_list(Detail)] || Detail <- Rest]]. + %% @doc normalize the semver so they can be compared -spec normalize(semver()) -> semver(). normalize({Vsn, Rest}) @@ -523,4 +556,19 @@ pes_test() -> ?assertMatch(true, not pes("2.7", "2.6.5")), ?assertMatch(true, not pes("2.5", "2.6.5")). +version_format_test() -> + ?assertEqual(["1", [], []], format({1, {[],[]}})), + ?assertEqual(["1", ".", "2", ".", "34", [], []], format({{1,2,34},{[],[]}})), + ?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))), + ?assertEqual(<<"1.2">>, erlang:iolist_to_binary(format({{1,2}, {[],[]}}))), + ?assertEqual(<<"1.2.2">>, erlang:iolist_to_binary(format({{1,2,2}, {[],[]}}))), + ?assertEqual(<<"1.99.2">>, erlang:iolist_to_binary(format({{1,99,2}, {[],[]}}))), + ?assertEqual(<<"1.99.2-alpha">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>],[]}}))), + ?assertEqual(<<"1.99.2-alpha.1">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>,1], []}}))), + ?assertEqual(<<"1.99.2+build.1.a36">>, + erlang:iolist_to_binary(format({{1,99,2}, {[], [<<"build">>, 1, <<"a36">>]}}))), + ?assertEqual(<<"1.99.2-alpha.1+build.1.a36">>, + erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>, 1], [<<"build">>, 1, <<"a36">>]}}))), + ?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))). + -endif. From 5105df48f956c0b9a2272a553eb452228832a644 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sun, 16 Sep 2012 13:07:17 -0500 Subject: [PATCH 038/240] minor whitespace cleanup for ec_semver Signed-off-by: Jordan Wilberding --- src/ec_semver.erl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 83bf6ef..0d8b40b 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -245,9 +245,6 @@ internal_pes(VsnA, {{LM, LMI, LP}, _}) -> internal_pes(Vsn, LVsn) -> gte(Vsn, LVsn). - - - %%%=================================================================== %%% Test Functions %%%=================================================================== @@ -275,7 +272,6 @@ eql_test() -> ?assertMatch(true, not eql("1.0.0+build.1", "1.0.1+build.2")). - gt_test() -> ?assertMatch(true, gt("1.0.0-alpha.1", "1.0.0-alpha")), From b4ab414419d544d9f8989e055bed8b8f6c6bc747 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 17 Sep 2012 09:38:32 -0500 Subject: [PATCH 039/240] support four primary version numbers of in parsing The OTP Versions distributed with erlang tend to have four version numbers not three. This is a fairly minor deviation from semver that we can support. Basically, the semver parser treats the fourth version in exactly the same way as the other three. Signed-off-by: Jordan Wilberding --- src/ec_semver.erl | 99 ++++++++++++++++++++++++++++++++-------- src/ec_semver_parser.peg | 4 +- 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 0d8b40b..0566322 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -1,3 +1,4 @@ + %%%------------------------------------------------------------------- %%% @copyright (C) 2011, Erlware LLC %%% @doc @@ -28,16 +29,18 @@ %%% Public Types %%%=================================================================== --type major_minor_patch() :: +-type major_minor_patch_minpatch() :: non_neg_integer() | {non_neg_integer(), non_neg_integer()} - | {non_neg_integer(), non_neg_integer(), non_neg_integer()}. + | {non_neg_integer(), non_neg_integer(), non_neg_integer()} + | {non_neg_integer(), non_neg_integer(), + non_neg_integer(), non_neg_integer()}. -type alpha_part() :: integer() | binary() | string(). -type alpha_info() :: {PreRelease::[alpha_part()], BuildVersion::[alpha_part()]}. --type semver() :: {major_minor_patch(), alpha_info()}. +-type semver() :: {major_minor_patch_minpatch(), alpha_info()}. -type version_string() :: string() | binary(). @@ -72,6 +75,13 @@ format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) -> erlang:integer_to_list(Min), ".", erlang:integer_to_list(Patch), format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]; +format({{Maj, Min, Patch, MinPatch}, {AlphaPart, BuildPart}}) -> + [erlang:integer_to_list(Maj), ".", + erlang:integer_to_list(Min), ".", + erlang:integer_to_list(Patch), ".", + erlang:integer_to_list(MinPatch), + format_vsn_rest(<<"-">>, AlphaPart), format_vsn_rest(<<"+">>, BuildPart)]. %% @doc test for quality between semver versions @@ -172,17 +182,20 @@ pes(VsnA, VsnB) -> %% @doc helper function for the peg grammer to parse the iolist into a semver -spec internal_parse_version(iolist()) -> semver(). internal_parse_version([MMP, AlphaPart, BuildPart, _]) -> - {parse_major_minor_patch(MMP), {parse_alpha_part(AlphaPart), - parse_alpha_part(BuildPart)}}. + {parse_major_minor_patch_minpatch(MMP), {parse_alpha_part(AlphaPart), + parse_alpha_part(BuildPart)}}. %% @doc helper function for the peg grammer to parse the iolist into a major_minor_patch --spec parse_major_minor_patch(iolist()) -> major_minor_patch(). -parse_major_minor_patch([MajVsn, [], []]) -> +-spec parse_major_minor_patch_minpatch(iolist()) -> major_minor_patch_minpatch(). +parse_major_minor_patch_minpatch([MajVsn, [], [], []]) -> MajVsn; -parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], []]) -> +parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [], []]) -> {MajVsn, MinVsn}; -parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn]]) -> - {MajVsn, MinVsn, PatchVsn}. +parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn], []]) -> + {MajVsn, MinVsn, PatchVsn}; +parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], + [<<".">>, PatchVsn], [<<".">>, MinPatch]]) -> + {MajVsn, MinVsn, PatchVsn, MinPatch}. %% @doc helper function for the peg grammer to parse the iolist into an alpha part -spec parse_alpha_part(iolist()) -> [alpha_part()]. @@ -226,22 +239,29 @@ format_vsn_rest(TypeMark, [Head | Rest]) -> -spec normalize(semver()) -> semver(). normalize({Vsn, Rest}) when erlang:is_integer(Vsn) -> - {{Vsn, 0, 0}, Rest}; + {{Vsn, 0, 0, 0}, Rest}; normalize({{Maj, Min}, Rest}) -> - {{Maj, Min, 0}, Rest}; -normalize(Other) -> + {{Maj, Min, 0, 0}, Rest}; +normalize({{Maj, Min, Patch}, Rest}) -> + {{Maj, Min, Patch, 0}, Rest}; +normalize(Other = {{_, _, _, _}, {_,_}}) -> Other. %% @doc to do the pessimistic compare we need a parsed semver. This is %% the internal implementation of the of the pessimistic run. The %% external just ensures that versions are parsed. +-spec internal_pes(semver(), semver()) -> boolean(). internal_pes(VsnA, {{LM, LMI}, _}) -> gte(VsnA, {{LM, LMI, 0}, {[], []}}) andalso - lt(VsnA, {{LM + 1, 0, 0}, {[], []}}); + lt(VsnA, {{LM + 1, 0, 0, 0}, {[], []}}); internal_pes(VsnA, {{LM, LMI, LP}, _}) -> gte(VsnA, {{LM, LMI, LP}, {[], []}}) andalso - lt(VsnA, {{LM, LMI + 1, 0}, {[], []}}); + lt(VsnA, {{LM, LMI + 1, 0, 0}, {[], []}}); +internal_pes(VsnA, {{LM, LMI, LP, LMP}, _}) -> + gte(VsnA, {{LM, LMI, LP, LMP}, {[], []}}) + andalso + lt(VsnA, {{LM, LMI, LP + 1, 0}, {[], []}}); internal_pes(Vsn, LVsn) -> gte(Vsn, LVsn). @@ -261,24 +281,38 @@ eql_test() -> "1.0.0")), ?assertMatch(true, eql("1.0.0", "1")), + ?assertMatch(true, eql("1.0.0.0", + "1")), ?assertMatch(true, eql("1.0+alpha.1", "1.0.0+alpha.1")), ?assertMatch(true, eql("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), + ?assertMatch(true, eql("1.0-alpha.1+build.1", + "1.0.0.0-alpha.1+build.1")), ?assertMatch(true, not eql("1.0.0", "1.0.1")), ?assertMatch(true, not eql("1.0.0-alpha", "1.0.1+alpha")), ?assertMatch(true, not eql("1.0.0+build.1", - "1.0.1+build.2")). + "1.0.1+build.2")), + ?assertMatch(true, not eql("1.0.0.0+build.1", + "1.0.0.1+build.2")). gt_test() -> ?assertMatch(true, gt("1.0.0-alpha.1", "1.0.0-alpha")), + ?assertMatch(true, gt("1.0.0.1-alpha.1", + "1.0.0.1-alpha")), + ?assertMatch(true, gt("1.0.0.4-alpha.1", + "1.0.0.2-alpha")), + ?assertMatch(true, gt("1.0.0.0-alpha.1", + "1.0.0-alpha")), ?assertMatch(true, gt("1.0.0-beta.2", "1.0.0-alpha.1")), ?assertMatch(true, gt("1.0.0-beta.11", "1.0.0-beta.2")), + ?assertMatch(true, gt("1.0.0-beta.11", + "1.0.0.0-beta.2")), ?assertMatch(true, gt("1.0.0-rc.1", "1.0.0-beta.11")), ?assertMatch(true, gt("1.0.0-rc.1+build.1", "1.0.0-rc.1")), ?assertMatch(true, gt("1.0.0", "1.0.0-rc.1+build.1")), @@ -286,10 +320,14 @@ gt_test() -> ?assertMatch(true, gt("1.3.7+build", "1.0.0+0.3.7")), ?assertMatch(true, gt("1.3.7+build.2.b8f12d7", "1.3.7+build")), + ?assertMatch(true, gt("1.3.7+build.2.b8f12d7", + "1.3.7.0+build")), ?assertMatch(true, gt("1.3.7+build.11.e0f985a", "1.3.7+build.2.b8f12d7")), ?assertMatch(true, not gt("1.0.0-alpha", "1.0.0-alpha.1")), + ?assertMatch(true, not gt("1.0.0-alpha", + "1.0.0.0-alpha.1")), ?assertMatch(true, not gt("1.0.0-alpha.1", "1.0.0-beta.2")), ?assertMatch(true, not gt("1.0.0-beta.2", @@ -324,12 +362,16 @@ gt_test() -> lt_test() -> ?assertMatch(true, lt("1.0.0-alpha", "1.0.0-alpha.1")), + ?assertMatch(true, lt("1.0.0-alpha", + "1.0.0.0-alpha.1")), ?assertMatch(true, lt("1.0.0-alpha.1", "1.0.0-beta.2")), ?assertMatch(true, lt("1.0.0-beta.2", "1.0.0-beta.11")), ?assertMatch(true, lt("1.0.0-beta.11", "1.0.0-rc.1")), + ?assertMatch(true, lt("1.0.0.1-beta.11", + "1.0.0.1-rc.1")), ?assertMatch(true, lt("1.0.0-rc.1", "1.0.0-rc.1+build.1")), ?assertMatch(true, lt("1.0.0-rc.1+build.1", @@ -346,9 +388,11 @@ lt_test() -> "1.0.0-alpha")), ?assertMatch(true, not lt("1", "1.0.0")), + ?assertMatch(true, lt("1", + "1.0.0.1")), ?assertMatch(true, not lt("1.0", "1.0.0")), - ?assertMatch(true, not lt("1.0.0", + ?assertMatch(true, not lt("1.0.0.0", "1")), ?assertMatch(true, not lt("1.0+alpha.1", "1.0.0+alpha.1")), @@ -384,12 +428,18 @@ gte_test() -> ?assertMatch(true, gte("1.0.0", "1")), + ?assertMatch(true, gte("1.0.0.0", + "1")), + ?assertMatch(true, gte("1.0+alpha.1", "1.0.0+alpha.1")), ?assertMatch(true, gte("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), + ?assertMatch(true, gte("1.0.0-alpha.1+build.1", + "1.0.0.0-alpha.1+build.1")), + ?assertMatch(true, gte("1.0.0-alpha.1", "1.0.0-alpha")), ?assertMatch(true, gte("1.0.0-beta.2", @@ -458,6 +508,8 @@ lte_test() -> "1")), ?assertMatch(true, lte("1.0+alpha.1", "1.0.0+alpha.1")), + ?assertMatch(true, lte("1.0.0.0+alpha.1", + "1.0.0+alpha.1")), ?assertMatch(true, lte("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), ?assertMatch(true, not lt("1.0.0-alpha.1", @@ -476,7 +528,6 @@ lte_test() -> ?assertMatch(true, not lt("1.3.7+build.11.e0f985a", "1.3.7+build.2.b8f12d7")). - between_test() -> ?assertMatch(true, between("1.0.0-alpha", "1.0.0-alpha.3", @@ -493,6 +544,10 @@ between_test() -> ?assertMatch(true, between("1.0.0-rc.1", "1.0.0-rc.1+build.3", "1.0.0-rc.1+build.1")), + + ?assertMatch(true, between("1.0.0.0-rc.1", + "1.0.0-rc.1+build.3", + "1.0.0-rc.1+build.1")), ?assertMatch(true, between("1.0.0-rc.1+build.1", "1.0.0", "1.0.0-rc.33")), @@ -517,6 +572,10 @@ between_test() -> ?assertMatch(true, between("1.0", "1.0.0", "1.0.0")), + + ?assertMatch(true, between("1.0", + "1.0.0.0", + "1.0.0.0")), ?assertMatch(true, between("1.0.0", "1", "1")), @@ -549,7 +608,9 @@ pes_test() -> ?assertMatch(true, pes("2.6.7", "2.6.5")), ?assertMatch(true, pes("2.6.8", "2.6.5")), ?assertMatch(true, pes("2.6.9", "2.6.5")), + ?assertMatch(true, pes("2.6.0.9", "2.6.0.5")), ?assertMatch(true, not pes("2.7", "2.6.5")), + ?assertMatch(true, not pes("2.1.7", "2.1.6.5")), ?assertMatch(true, not pes("2.5", "2.6.5")). version_format_test() -> @@ -563,6 +624,8 @@ version_format_test() -> ?assertEqual(<<"1.99.2-alpha.1">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>,1], []}}))), ?assertEqual(<<"1.99.2+build.1.a36">>, erlang:iolist_to_binary(format({{1,99,2}, {[], [<<"build">>, 1, <<"a36">>]}}))), + ?assertEqual(<<"1.99.2.44+build.1.a36">>, + erlang:iolist_to_binary(format({{1,99,2,44}, {[], [<<"build">>, 1, <<"a36">>]}}))), ?assertEqual(<<"1.99.2-alpha.1+build.1.a36">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>, 1], [<<"build">>, 1, <<"a36">>]}}))), ?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))). diff --git a/src/ec_semver_parser.peg b/src/ec_semver_parser.peg index 9636d95..f505693 100644 --- a/src/ec_semver_parser.peg +++ b/src/ec_semver_parser.peg @@ -1,7 +1,7 @@ -semver <- major_minor_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !. +semver <- major_minor_patch_min_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !. ` ec_semver:internal_parse_version(Node) ` ; -major_minor_patch <- version_part ("." version_part)? ("." version_part)? ; +major_minor_patch_min_patch <- version_part ("." version_part)? ("." version_part)? ("." version_part)? ; version_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ; From eab58fb6605c3354bb9530db0c2cf79e3382ea5b Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 18 Sep 2012 17:18:34 -0700 Subject: [PATCH 040/240] export mkdir_p (this should have been done already) Signed-off-by: Jordan Wilberding --- src/ec_file.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ec_file.erl b/src/ec_file.erl index c5cbe56..f815a3a 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -11,6 +11,7 @@ copy/3, insecure_mkdtemp/0, mkdir_path/1, + mkdir_p/1, find/2, is_symlink/1, remove/1, From a9f2a771f018ef5efa3864d91bf888175c22c54f Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Tue, 18 Sep 2012 17:45:27 -0700 Subject: [PATCH 041/240] fix bug in ec_file:copy/3 spec Signed-off-by: Jordan Wilberding --- src/ec_file.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index f815a3a..37ad1b1 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -36,12 +36,12 @@ %% Types %%============================================================================ -type option() :: recursive. --type void() :: ok. + %%%=================================================================== %%% API %%%=================================================================== %% @doc copy an entire directory to another location. --spec copy(file:name(), file:name(), Options::[option()]) -> void(). +-spec copy(file:name(), file:name(), Options::[option()]) -> ok | {error, Reason::term()}. copy(From, To, []) -> copy(From, To); copy(From, To, [recursive] = Options) -> @@ -230,7 +230,7 @@ tmp() -> end. %% Copy the subfiles of the From directory to the to directory. --spec copy_subfiles(file:name(), file:name(), [option()]) -> void(). +-spec copy_subfiles(file:name(), file:name(), [option()]) -> {error, Reason::term()} | ok. copy_subfiles(From, To, Options) -> Fun = fun(ChildFrom) -> From f77afd43c31dce68664358e7bf1c32b02f45b39e Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 19 Oct 2012 08:57:23 -0500 Subject: [PATCH 042/240] add exists to ec_file Signed-off-by: Jordan Wilberding --- src/ec_file.erl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ec_file.erl b/src/ec_file.erl index 37ad1b1..45adb2a 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -7,6 +7,7 @@ -module(ec_file). -export([ + exists/1, copy/2, copy/3, insecure_mkdtemp/0, @@ -40,6 +41,15 @@ %%%=================================================================== %%% API %%%=================================================================== +-spec exists(file:filename()) -> boolean(). +exists(Filename) -> + case file:read_file_info(Filename) of + {ok, _} -> + true; + {error, _Reason} -> + false + end. + %% @doc copy an entire directory to another location. -spec copy(file:name(), file:name(), Options::[option()]) -> ok | {error, Reason::term()}. copy(From, To, []) -> @@ -314,6 +324,16 @@ setup_base_and_target() -> ok = file:write_file(NoName, DummyContents), {BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}. +exists_test() -> + BaseDir = insecure_mkdtemp(), + SourceDir = filename:join([BaseDir, "source1"]), + NoName = filename:join([SourceDir, "noname"]), + ok = file:make_dir(SourceDir), + Name1 = filename:join([SourceDir, "fileone"]), + ok = file:write_file(Name1, <<"Testn">>), + ?assertMatch(true, exists(Name1)), + ?assertMatch(false, exists(NoName)). + find_test() -> %% Create a directory in /tmp for the test. Clean everything afterwards {BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(), From 0db7042ff90ac420be8e4ebca21d11e153d845d6 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Wed, 19 Sep 2012 07:57:48 -0700 Subject: [PATCH 043/240] support reasonable versioning for erlware_commons You should get the latest and greatest rebar to build this. Signed-off-by: Jordan Wilberding --- src/erlware_commons.app.src | 2 +- src/erlware_commons.app.src.script | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/erlware_commons.app.src.script diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index 8aaa5f3..7e6111b 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.8.0"}, + {vsn, git}, {modules, []}, {registered, []}, {applications, [kernel, stdlib]}]}. diff --git a/src/erlware_commons.app.src.script b/src/erlware_commons.app.src.script new file mode 100644 index 0000000..381e7dc --- /dev/null +++ b/src/erlware_commons.app.src.script @@ -0,0 +1,22 @@ +%% -*- mode: Erlang; erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- + +[{application, AppName, Details0}] = CONFIG, + +%% Get the tag timestamp and minimal ref from the system. The +%% timestamp is really important from an ordering perspective. +{ok, RawRef} = rebar_utils:sh("git log -n 1 --pretty=format:'%ct.%h\n' .", []), +{ok, RawTag} = rebar_utils:sh("git describe --always --abbrev=0 --tags " + "`git log -n 1 --pretty=format:%h .`", []), + +%% Cleanup the tag and the Ref information. Basically leading 'v's and +%% whitespace needs to go away. +Tag = re:replace(RawTag, "(^v)|\\s", "", [global]), +Ref = re:replace(RawRef, "\\s", "", [global]), + +%% Create the valid [semver](http://semver.org) version from the tag +Vsn = erlang:binary_to_list(erlang:iolist_to_binary([Tag, "+build.", Ref])), + +%% Replace the old version with the new one +Details1 = lists:keyreplace(vsn, 1, Details0, {vsn, Vsn}), + +[{application, AppName, Details1}]. From 7e4ba401fd74572affcd4db13056c12c7b4b33bb Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 11 Oct 2012 10:01:45 -0500 Subject: [PATCH 044/240] support non-numeric versions in major/minor/patch/minor-patch This allows for two things. The first is support for non rigorous versions. However, it still fully supports semver. So if you have semver versions they work correctly, if you have alpha versions they also work correctly but using natural alpha ordering. Signed-off-by: Jordan Wilberding --- src/ec_semver.erl | 132 ++++++++++++++++++++++++++++----------- src/ec_semver_parser.peg | 5 +- 2 files changed, 99 insertions(+), 38 deletions(-) diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 0566322..ac810e5 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -29,12 +29,14 @@ %%% Public Types %%%=================================================================== +-type version_element() :: non_neg_integer() | binary(). + -type major_minor_patch_minpatch() :: - non_neg_integer() - | {non_neg_integer(), non_neg_integer()} - | {non_neg_integer(), non_neg_integer(), non_neg_integer()} - | {non_neg_integer(), non_neg_integer(), - non_neg_integer(), non_neg_integer()}. + version_element() + | {version_element(), version_element()} + | {version_element(), version_element(), version_element()} + | {version_element(), version_element(), + version_element(), version_element()}. -type alpha_part() :: integer() | binary() | string(). -type alpha_info() :: {PreRelease::[alpha_part()], @@ -53,37 +55,58 @@ %% @doc parse a string or binary into a valid semver representation -spec parse(any_version()) -> semver(). parse(Version) when erlang:is_list(Version) -> - ec_semver_parser:parse(Version); + case ec_semver_parser:parse(Version) of + {fail, _} -> + {erlang:iolist_to_binary(Version), {[],[]}}; + Good -> + Good + end; parse(Version) when erlang:is_binary(Version) -> - ec_semver_parser:parse(Version); + case ec_semver_parser:parse(Version) of + {fail, _} -> + {Version, {[],[]}}; + Good -> + Good + end; parse(Version) -> Version. -spec format(semver()) -> iolist(). format({Maj, {AlphaPart, BuildPart}}) - when erlang:is_integer(Maj) -> - [erlang:integer_to_list(Maj), + when erlang:is_integer(Maj); + erlang:is_binary(Maj) -> + [format_version_part(Maj), format_vsn_rest(<<"-">>, AlphaPart), format_vsn_rest(<<"+">>, BuildPart)]; format({{Maj, Min}, {AlphaPart, BuildPart}}) -> - [erlang:integer_to_list(Maj), ".", - erlang:integer_to_list(Min), + [format_version_part(Maj), ".", + format_version_part(Min), format_vsn_rest(<<"-">>, AlphaPart), format_vsn_rest(<<"+">>, BuildPart)]; format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) -> - [erlang:integer_to_list(Maj), ".", - erlang:integer_to_list(Min), ".", - erlang:integer_to_list(Patch), + [format_version_part(Maj), ".", + format_version_part(Min), ".", + format_version_part(Patch), format_vsn_rest(<<"-">>, AlphaPart), format_vsn_rest(<<"+">>, BuildPart)]; format({{Maj, Min, Patch, MinPatch}, {AlphaPart, BuildPart}}) -> - [erlang:integer_to_list(Maj), ".", - erlang:integer_to_list(Min), ".", - erlang:integer_to_list(Patch), ".", - erlang:integer_to_list(MinPatch), + [format_version_part(Maj), ".", + format_version_part(Min), ".", + format_version_part(Patch), ".", + format_version_part(MinPatch), format_vsn_rest(<<"-">>, AlphaPart), format_vsn_rest(<<"+">>, BuildPart)]. +-spec format_version_part(integer() | binary()) -> iolist(). +format_version_part(Vsn) + when erlang:is_integer(Vsn) -> + erlang:integer_to_list(Vsn); +format_version_part(Vsn) + when erlang:is_binary(Vsn) -> + Vsn. + + + %% @doc test for quality between semver versions -spec eql(any_version(), any_version()) -> boolean(). eql(VsnA, VsnB) -> @@ -238,7 +261,8 @@ format_vsn_rest(TypeMark, [Head | Rest]) -> %% @doc normalize the semver so they can be compared -spec normalize(semver()) -> semver(). normalize({Vsn, Rest}) - when erlang:is_integer(Vsn) -> + when erlang:is_binary(Vsn); + erlang:is_integer(Vsn) -> {{Vsn, 0, 0, 0}, Rest}; normalize({{Maj, Min}, Rest}) -> {{Maj, Min, 0, 0}, Rest}; @@ -251,14 +275,23 @@ normalize(Other = {{_, _, _, _}, {_,_}}) -> %% the internal implementation of the of the pessimistic run. The %% external just ensures that versions are parsed. -spec internal_pes(semver(), semver()) -> boolean(). -internal_pes(VsnA, {{LM, LMI}, _}) -> +internal_pes(VsnA, {{LM, LMI}, _}) + when erlang:is_integer(LM), + erlang:is_integer(LMI) -> gte(VsnA, {{LM, LMI, 0}, {[], []}}) andalso lt(VsnA, {{LM + 1, 0, 0, 0}, {[], []}}); -internal_pes(VsnA, {{LM, LMI, LP}, _}) -> +internal_pes(VsnA, {{LM, LMI, LP}, _}) + when erlang:is_integer(LM), + erlang:is_integer(LMI), + erlang:is_integer(LP) -> gte(VsnA, {{LM, LMI, LP}, {[], []}}) andalso lt(VsnA, {{LM, LMI + 1, 0, 0}, {[], []}}); -internal_pes(VsnA, {{LM, LMI, LP, LMP}, _}) -> +internal_pes(VsnA, {{LM, LMI, LP, LMP}, _}) + when erlang:is_integer(LM), + erlang:is_integer(LMI), + erlang:is_integer(LP), + erlang:is_integer(LMP) -> gte(VsnA, {{LM, LMI, LP, LMP}, {[], []}}) andalso lt(VsnA, {{LM, LMI, LP + 1, 0}, {[], []}}); @@ -289,6 +322,9 @@ eql_test() -> "1.0.0-alpha.1+build.1")), ?assertMatch(true, eql("1.0-alpha.1+build.1", "1.0.0.0-alpha.1+build.1")), + ?assertMatch(true, eql("aa", "aa")), + ?assertMatch(true, eql("AA.BB", "AA.BB")), + ?assertMatch(true, eql("BBB-super", "BBB-super")), ?assertMatch(true, not eql("1.0.0", "1.0.1")), ?assertMatch(true, not eql("1.0.0-alpha", @@ -296,7 +332,9 @@ eql_test() -> ?assertMatch(true, not eql("1.0.0+build.1", "1.0.1+build.2")), ?assertMatch(true, not eql("1.0.0.0+build.1", - "1.0.0.1+build.2")). + "1.0.0.1+build.2")), + ?assertMatch(true, not eql("FFF", "BBB")), + ?assertMatch(true, not eql("1", "1BBBB")). gt_test() -> ?assertMatch(true, gt("1.0.0-alpha.1", @@ -324,6 +362,8 @@ gt_test() -> "1.3.7.0+build")), ?assertMatch(true, gt("1.3.7+build.11.e0f985a", "1.3.7+build.2.b8f12d7")), + ?assertMatch(true, gt("aa.cc", + "aa.bb")), ?assertMatch(true, not gt("1.0.0-alpha", "1.0.0-alpha.1")), ?assertMatch(true, not gt("1.0.0-alpha", @@ -350,6 +390,10 @@ gt_test() -> "1.0.0-alpha")), ?assertMatch(true, not gt("1", "1.0.0")), + ?assertMatch(true, not gt("aa.bb", + "aa.bb")), + ?assertMatch(true, not gt("aa.cc", + "aa.dd")), ?assertMatch(true, not gt("1.0", "1.0.0")), ?assertMatch(true, not gt("1.0.0", @@ -390,12 +434,15 @@ lt_test() -> "1.0.0")), ?assertMatch(true, lt("1", "1.0.0.1")), + ?assertMatch(true, lt("AA.DD", + "AA.EE")), ?assertMatch(true, not lt("1.0", "1.0.0")), ?assertMatch(true, not lt("1.0.0.0", "1")), ?assertMatch(true, not lt("1.0+alpha.1", "1.0.0+alpha.1")), + ?assertMatch(true, not lt("AA.DD", "AA.CC")), ?assertMatch(true, not lt("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), ?assertMatch(true, not lt("1.0.0-alpha.1", @@ -414,7 +461,6 @@ lt_test() -> ?assertMatch(true, not lt("1.3.7+build.11.e0f985a", "1.3.7+build.2.b8f12d7")). - gte_test() -> ?assertMatch(true, gte("1.0.0-alpha", "1.0.0-alpha")), @@ -439,13 +485,14 @@ gte_test() -> ?assertMatch(true, gte("1.0.0-alpha.1+build.1", "1.0.0.0-alpha.1+build.1")), - ?assertMatch(true, gte("1.0.0-alpha.1", "1.0.0-alpha")), ?assertMatch(true, gte("1.0.0-beta.2", "1.0.0-alpha.1")), ?assertMatch(true, gte("1.0.0-beta.11", "1.0.0-beta.2")), + ?assertMatch(true, gte("aa.bb", "aa.bb")), + ?assertMatch(true, gte("dd", "aa")), ?assertMatch(true, gte("1.0.0-rc.1", "1.0.0-beta.11")), ?assertMatch(true, gte("1.0.0-rc.1+build.1", "1.0.0-rc.1")), ?assertMatch(true, gte("1.0.0", "1.0.0-rc.1+build.1")), @@ -457,6 +504,7 @@ gte_test() -> "1.3.7+build.2.b8f12d7")), ?assertMatch(true, not gte("1.0.0-alpha", "1.0.0-alpha.1")), + ?assertMatch(true, not gte("CC", "DD")), ?assertMatch(true, not gte("1.0.0-alpha.1", "1.0.0-beta.2")), ?assertMatch(true, not gte("1.0.0-beta.2", @@ -512,20 +560,23 @@ lte_test() -> "1.0.0+alpha.1")), ?assertMatch(true, lte("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), - ?assertMatch(true, not lt("1.0.0-alpha.1", + ?assertMatch(true, lte("aa","cc")), + ?assertMatch(true, lte("cc","cc")), + ?assertMatch(true, not lte("1.0.0-alpha.1", "1.0.0-alpha")), - ?assertMatch(true, not lt("1.0.0-beta.2", + ?assertMatch(true, not lte("cc", "aa")), + ?assertMatch(true, not lte("1.0.0-beta.2", "1.0.0-alpha.1")), - ?assertMatch(true, not lt("1.0.0-beta.11", + ?assertMatch(true, not lte("1.0.0-beta.11", "1.0.0-beta.2")), - ?assertMatch(true, not lt("1.0.0-rc.1", "1.0.0-beta.11")), - ?assertMatch(true, not lt("1.0.0-rc.1+build.1", "1.0.0-rc.1")), - ?assertMatch(true, not lt("1.0.0", "1.0.0-rc.1+build.1")), - ?assertMatch(true, not lt("1.0.0+0.3.7", "1.0.0")), - ?assertMatch(true, not lt("1.3.7+build", "1.0.0+0.3.7")), - ?assertMatch(true, not lt("1.3.7+build.2.b8f12d7", + ?assertMatch(true, not lte("1.0.0-rc.1", "1.0.0-beta.11")), + ?assertMatch(true, not lte("1.0.0-rc.1+build.1", "1.0.0-rc.1")), + ?assertMatch(true, not lte("1.0.0", "1.0.0-rc.1+build.1")), + ?assertMatch(true, not lte("1.0.0+0.3.7", "1.0.0")), + ?assertMatch(true, not lte("1.3.7+build", "1.0.0+0.3.7")), + ?assertMatch(true, not lte("1.3.7+build.2.b8f12d7", "1.3.7+build")), - ?assertMatch(true, not lt("1.3.7+build.11.e0f985a", + ?assertMatch(true, not lte("1.3.7+build.11.e0f985a", "1.3.7+build.2.b8f12d7")). between_test() -> @@ -585,6 +636,9 @@ between_test() -> ?assertMatch(true, between("1.0-alpha.1+build.1", "1.0.0-alpha.1+build.1", "1.0.0-alpha.1+build.1")), + ?assertMatch(true, between("aaa", + "ddd", + "cc")), ?assertMatch(true, not between("1.0.0-alpha.1", "1.0.0-alpha.22", "1.0.0")), @@ -594,13 +648,16 @@ between_test() -> ?assertMatch(true, not between("1.0.0-beta.1", "1.0.0-beta.11", "1.0.0-alpha")), - ?assertMatch(true, not between("1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.22")). + ?assertMatch(true, not between("1.0.0-beta.11", "1.0.0-rc.1", + "1.0.0-rc.22")), + ?assertMatch(true, not between("aaa", "ddd", "zzz")). pes_test() -> ?assertMatch(true, pes("2.6.0", "2.6")), ?assertMatch(true, pes("2.7", "2.6")), ?assertMatch(true, pes("2.8", "2.6")), ?assertMatch(true, pes("2.9", "2.6")), + ?assertMatch(true, pes("A.B", "A.A")), ?assertMatch(true, not pes("3.0.0", "2.6")), ?assertMatch(true, not pes("2.5", "2.6")), ?assertMatch(true, pes("2.6.5", "2.6.5")), @@ -611,11 +668,14 @@ pes_test() -> ?assertMatch(true, pes("2.6.0.9", "2.6.0.5")), ?assertMatch(true, not pes("2.7", "2.6.5")), ?assertMatch(true, not pes("2.1.7", "2.1.6.5")), + ?assertMatch(true, not pes("A.A", "A.B")), ?assertMatch(true, not pes("2.5", "2.6.5")). version_format_test() -> ?assertEqual(["1", [], []], format({1, {[],[]}})), ?assertEqual(["1", ".", "2", ".", "34", [], []], format({{1,2,34},{[],[]}})), + ?assertEqual(<<"a">>, erlang:iolist_to_binary(format({<<"a">>, {[],[]}}))), + ?assertEqual(<<"a.b">>, erlang:iolist_to_binary(format({{<<"a">>,<<"b">>}, {[],[]}}))), ?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))), ?assertEqual(<<"1.2">>, erlang:iolist_to_binary(format({{1,2}, {[],[]}}))), ?assertEqual(<<"1.2.2">>, erlang:iolist_to_binary(format({{1,2,2}, {[],[]}}))), diff --git a/src/ec_semver_parser.peg b/src/ec_semver_parser.peg index f505693..09779ae 100644 --- a/src/ec_semver_parser.peg +++ b/src/ec_semver_parser.peg @@ -3,9 +3,10 @@ semver <- major_minor_patch_min_patch ("-" alpha_part ("." alpha_part)*)? ("+" a major_minor_patch_min_patch <- version_part ("." version_part)? ("." version_part)? ("." version_part)? ; -version_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ; +version_part <- numeric_part / alpha_part ; -alpha_part <- [A-Za-z0-9-]+ ; +numeric_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ; +alpha_part <- [A-Za-z0-9]+ `erlang:iolist_to_binary(Node)` ; %% This only exists to get around a bug in erlang where if %% warnings_as_errors is specified `nowarn` directives are ignored From 1540fb16521ccec7d22268d05f1bf2fa485fea66 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 19 Oct 2012 18:20:07 -0500 Subject: [PATCH 045/240] cleanup the rebar config Signed-off-by: Jordan Wilberding --- rebar.config | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 2c3cad3..cd5d68a 100644 --- a/rebar.config +++ b/rebar.config @@ -1,12 +1,20 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- -%% These are all only compile time dependencies +%% Dependencies ================================================================ {deps, [{neotoma, "", - {git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5.1"}}}, + {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}]}. {erl_first_files, ["ec_dictionary"]}. +%% Compiler Options ============================================================ {erl_opts, [debug_info, warnings_as_errors]}. + +%% EUnit ======================================================================= +{eunit_opts, [verbose, + {report, {eunit_surefire, [{dir, "."}]}}]}. + +{cover_enabled, true}. +{cover_print_enabled, true}. From c4887e202193aa21171288598d9b9ff7f40ed3a0 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 19 Oct 2012 18:22:03 -0500 Subject: [PATCH 046/240] enable the rebar semver plugin on erlware_commons Signed-off-by: Jordan Wilberding --- rebar.config | 7 ++++++- src/erlware_commons.app.src | 2 +- src/erlware_commons.app.src.script | 22 ---------------------- 3 files changed, 7 insertions(+), 24 deletions(-) delete mode 100644 src/erlware_commons.app.src.script diff --git a/rebar.config b/rebar.config index cd5d68a..08863d2 100644 --- a/rebar.config +++ b/rebar.config @@ -3,7 +3,9 @@ %% Dependencies ================================================================ {deps, [{neotoma, "", {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, - {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}]}. + {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}, + {rebar_vsn_plugin, ".*", {git, "https://github.com/erlware/rebar_vsn_plugin.git", + {branch, "master"}}}]}. {erl_first_files, ["ec_dictionary"]}. @@ -18,3 +20,6 @@ {cover_enabled, true}. {cover_print_enabled, true}. + +%% Rebar Plugins ============================================================== +{plugins, [rebar_vsn_plugin]}. diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index 7e6111b..042c56a 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, git}, + {vsn, "semver"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib]}]}. diff --git a/src/erlware_commons.app.src.script b/src/erlware_commons.app.src.script deleted file mode 100644 index 381e7dc..0000000 --- a/src/erlware_commons.app.src.script +++ /dev/null @@ -1,22 +0,0 @@ -%% -*- mode: Erlang; erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- - -[{application, AppName, Details0}] = CONFIG, - -%% Get the tag timestamp and minimal ref from the system. The -%% timestamp is really important from an ordering perspective. -{ok, RawRef} = rebar_utils:sh("git log -n 1 --pretty=format:'%ct.%h\n' .", []), -{ok, RawTag} = rebar_utils:sh("git describe --always --abbrev=0 --tags " - "`git log -n 1 --pretty=format:%h .`", []), - -%% Cleanup the tag and the Ref information. Basically leading 'v's and -%% whitespace needs to go away. -Tag = re:replace(RawTag, "(^v)|\\s", "", [global]), -Ref = re:replace(RawRef, "\\s", "", [global]), - -%% Create the valid [semver](http://semver.org) version from the tag -Vsn = erlang:binary_to_list(erlang:iolist_to_binary([Tag, "+build.", Ref])), - -%% Replace the old version with the new one -Details1 = lists:keyreplace(vsn, 1, Details0, {vsn, Vsn}), - -[{application, AppName, Details1}]. From b5371974d15fbf074f0e7c26597b2e95dc642c12 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 08:54:49 -0500 Subject: [PATCH 047/240] add fullpath to the makefile Signed-off-by: Jordan Wilberding --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 538d561..55ab0fd 100644 --- a/Makefile +++ b/Makefile @@ -34,11 +34,11 @@ test: compile $(ERLWARE_COMMONS_PLT): @echo Building local plt at $(ERLWARE_COMMONS_PLT) @echo - - dialyzer --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \ + - dialyzer --fullpath --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \ --apps erts kernel stdlib eunit -r deps dialyzer: $(ERLWARE_COMMONS_PLT) - dialyzer --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src + dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src typer: typer --plt $(ERLWARE_COMMONS_PLT) -r ./src From 1a1b87bf53e899a5525710018ac83c1280e67191 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 08:55:41 -0500 Subject: [PATCH 048/240] add a clean and rebuild task to makefile Signed-off-by: Jordan Wilberding --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 55ab0fd..7ee2120 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ endif ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt -.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript +.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps \ + rebuild all: compile test doc dialyzer @@ -62,3 +63,5 @@ clean: distclean: clean rm -rf $(ERLWARE_COMMONS_PLT) rm -rvf $(CURDIR)/deps/* + +rebuild: distclean all From dda4c8558653d907dc1e7c27e2509bd6cdadc2f6 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 08:56:00 -0500 Subject: [PATCH 049/240] reorder default tasks so dialyzer is run after compile Signed-off-by: Jordan Wilberding --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7ee2120..ab8b307 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt .PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps \ rebuild -all: compile test doc dialyzer +all: compile dialyzer doc test get-deps: $(REBAR) get-deps From 0e10d59b3af1ba6aa6ea2dde0d19a94a07bca709 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 11:49:26 -0500 Subject: [PATCH 050/240] add Stephen Marsh's plists to the system origin: http://code.google.com/p/plists/ detail: http://plists.wordpress.com/2007/09/20/introducing-plists-an-erlang-module-for-doing-list-operations-in-parallel/ Signed-off-by: Jordan Wilberding --- src/plists.erl | 858 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 858 insertions(+) create mode 100644 src/plists.erl diff --git a/src/plists.erl b/src/plists.erl new file mode 100644 index 0000000..688d5a5 --- /dev/null +++ b/src/plists.erl @@ -0,0 +1,858 @@ +% @author Stephen Marsh +% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] +% @doc plists is a drop-in replacement for module +% lists, +% making most list operations parallel. It can operate on each element in +% parallel, for IO-bound operations, on sublists in parallel, for +% taking advantage of multi-core machines with CPU-bound operations, and +% across erlang nodes, for parallizing inside a cluster. It handles +% errors and node failures. It can be configured, tuned, and tweaked to +% get optimal performance while minimizing overhead. +% +% Almost all the functions are +% identical to equivalent functions in lists, returning exactly the same +% result, and having both a form with an identical syntax that operates on +% each element in parallel and a form which takes an optional "malt", +% a specification for how to parallize the operation. +% +% fold is the one exception, parallel fold is different from linear fold. +% This module also include a simple mapreduce implementation, and the +% function runmany. All the other functions are implemented with runmany, +% which is as a generalization of parallel list operations. +% +% == Malts == +% A malt specifies how to break a list into sublists, and can optionally +% specify a timeout, which nodes to run on, and how many processes to start +% per node. +% +% Malt = MaltComponent | [MaltComponent]
+% MaltComponent = SubListSize::integer() | {processes, integer()} | +% {processes, schedulers} | +% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
+% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | +% {Node::atom(), schedulers} +% +% An integer can be given to specify the exact size for +% sublists. 1 is a good choice for IO-bound operations and when +% the operation on each list element is expensive. Larger numbers +% minimize overhead and are faster for cheap operations. +% +% If the integer is omitted, and +% you have specified a {processes, X}, the list is +% split into X sublists. This is only +% useful when the time to process each element is close to identical and you +% know exactly how many lines of execution are available to you. +% +% If neither of the above applies, the sublist size defaults to 1. +% +% You can use {processes, X} to have the list processed +% by X processes on the local machine. A good choice for X is the number of +% lines of execution (cores) the machine provides. This can be done +% automatically with {processes, schedulers}, which sets +% the number of processes to the number of schedulers in the erlang virtual +% machine (probably equal to the number of cores). +% +% {timeout, Milliseconds} specifies a timeout. This is a timeout for the entire +% operation, both operating on the sublists and combining the results. +% exit(timeout) is evaluated if the timeout is exceeded. +% +% {nodes, NodeList} specifies that the operation should be done across nodes. +% Every element of NodeList is of the form {NodeName, NumProcesses} or +% NodeName, which means the same as {NodeName, 1}. plists runs +% NumProcesses processes on NodeName concurrently. A good choice for +% NumProcesses is the number of lines of execution (cores) a node provides +% plus one. This ensures the node is completely busy even when +% fetching a new sublist. This can be done automatically with +% {NodeName, schedulers}, in which case +% plists uses a cached value if it has one, and otherwise finds the number of +% schedulers in the remote node and adds one. This will ensure at least one +% busy process per core (assuming the node has a scheduler for each core). +% +% plists is able to recover if a node goes down. +% If all nodes go down, exit(allnodescrashed) is evaluated. +% +% Any of the above may be used as a malt, or may be combined into a list. +% {nodes, NodeList} and {processes, X} may not be combined. +% +% === Examples === +% % start a process for each element (1-element sublists)
+% 1 +% +% % start a process for each ten elements (10-element sublists)
+% 10 +% +% % split the list into two sublists and process in two processes
+% {processes, 2} +% +% % split the list into X sublists and process in X processes,
+% % where X is the number of cores in the machine
+% {processes, schedulers} +% +% % split the list into 10-element sublists and process in two processes
+% [10, {processes, 2}] +% +% % timeout after one second. Assumes that a process should be started
+% % for each element.
+% {timeout, 1000} +% +% % Runs 3 processes at a time on apple@desktop, +% and 2 on orange@laptop
+% % This is the best way to utilize all the CPU-power of a dual-core
+% % desktop and a single-core laptop. Assumes that the list should be
+% % split into 1-element sublists.
+% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} +% +% Like above, but makes plists figure out how many processes to use. +% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} +% +% % Gives apple and orange three seconds to process the list as
+% % 100-element sublists.
+% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] +% +% === Aside: Why Malt? === +% I needed a word for this concept, so maybe my subconsciousness gave me one by +% making me misspell multiply. Maybe it is an acronym for Malt is A List +% Tearing Specification. Maybe it is a beer metaphor, suggesting that code +% only runs in parallel if bribed with spirits. It's jargon, learn it +% or you can't be part of the in-group. +% +% == Messages and Errors == +% plists assures that no extraneous messages are left in or will later +% enter the message queue. This is guaranteed even in the event of an error. +% +% Errors in spawned processes are caught and propagated to the calling +% process. If you invoke +% +% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). +% +% you get a badarith error, exactly like when you use lists:map. +% +% plists uses monitors to watch the processes it spawns. It is not a good idea +% to invoke plists when you are already monitoring processes. If one of them +% does a non-normal exit, plists receives the 'DOWN' message believing it to be +% from one of its own processes. The error propagation system goes into +% effect, which results in the error occuring in the calling process. +% +% == License == +% The MIT License +% +% Copyright (c) 2007 Stephen Marsh +% +% Permission is hereby granted, free of charge, to any person obtaining a copy +% of this software and associated documentation files (the "Software"), to deal +% in the Software without restriction, including without limitation the rights +% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +% copies of the Software, and to permit persons to whom the Software is +% furnished to do so, subject to the following conditions: +% +% The above copyright notice and this permission notice shall be included in +% all copies or substantial portions of the Software. +% +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +% THE SOFTWARE. + + +-module(plists). +-export([all/2, all/3, any/2, any/3, filter/2, filter/3, +fold/3, fold/4, fold/5, foreach/2, foreach/3, map/2, map/3, +partition/2, partition/3, sort/1, sort/2, sort/3, +usort/1, usort/2, usort/3, mapreduce/2, mapreduce/3, mapreduce/5, +runmany/3, runmany/4]). + +% Everything here is defined in terms of runmany. +% The following methods are convient interfaces to runmany. + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> bool() +all(Fun, List) -> + all(Fun, List, 1). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> bool() +all(Fun, List, Malt) -> + try runmany(fun (L) -> + B = lists:all(Fun, L), + if B -> + nil; + true -> + exit(notall) + end + end, + fun (_A1, _A2) -> + nil + end, + List, Malt) of + _ -> + true + catch exit:notall -> + false + end. + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> bool() +any(Fun, List) -> + any(Fun, List, 1). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> bool() +any(Fun, List, Malt) -> + try runmany(fun (L) -> + B = lists:any(Fun, L), + if B -> + exit(any); + true -> + nil + end + end, + fun (_A1, _A2) -> + nil + end, + List, Malt) of + _ -> + false + catch exit:any -> + true + end. + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +filter(Fun, List) -> + filter(Fun, List, 1). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> list() +filter(Fun, List, Malt) -> + runmany(fun (L) -> + lists:filter(Fun, L) + end, + {reverse, fun (A1, A2) -> + A1 ++ A2 + end}, + List, Malt). + +% Note that with parallel fold there is not foldl and foldr, +% instead just one fold that can fuse Accumlators. + +% @doc Like below, but assumes 1 as the Malt. This function is almost useless, +% and is intended only to aid converting code from using lists to plists. +% @spec (Fun, InitAcc, List) -> term() +fold(Fun, InitAcc, List) -> + fold(Fun, Fun, InitAcc, List, 1). + +% @doc Like below, but uses the Fun as the Fuse by default. +% @spec (Fun, InitAcc, List, Malt) -> term() +fold(Fun, InitAcc, List, Malt) -> + fold(Fun, Fun, InitAcc, List, Malt). + +% @doc fold is more complex when made parallel. There is no foldl and foldr, +% accumulators aren't passed in any defined order. +% The list is split into sublists which are folded together. Fun is +% identical to the function passed to lists:fold[lr], it takes +% (an element, and the accumulator) and returns -> a new accumulator. +% It is used for the initial stage of folding sublists. Fuse fuses together +% the results, it takes (Results1, Result2) and returns -> a new result. +% By default sublists are fused left to right, each result of a fuse being +% fed into the first element of the next fuse. The result of the last fuse +% is the result. +% +% Fusing may also run in parallel using a recursive algorithm, +% by specifying the fuse as {recursive, Fuse}. See +% the discussion in {@link runmany/4}. +% +% Malt is the malt for the initial folding of sublists, and for the +% possible recursive fuse. +% @spec (Fun, Fuse, InitAcc, List, Malt) -> term() +fold(Fun, Fuse, InitAcc, List, Malt) -> + Fun2 = fun (L) -> lists:foldl(Fun, InitAcc, L) end, + runmany(Fun2, Fuse, List, Malt). + +% @doc Similiar to foreach in module +% lists +% except it makes no guarantee about the order it processes list elements. +% @spec (Fun, List) -> void() +foreach(Fun, List) -> + foreach(Fun, List, 1). + +% @doc Similiar to foreach in module +% lists +% except it makes no guarantee about the order it processes list elements. +% @spec (Fun, List, Malt) -> void() +foreach(Fun, List, Malt) -> + runmany(fun (L) -> + lists:foreach(Fun, L) + end, + fun (_A1, _A2) -> + ok + end, + List, Malt). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +map(Fun, List) -> + map(Fun, List, 1). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> list() +map(Fun, List, Malt) -> + runmany(fun (L) -> + lists:map(Fun, L) + end, + {reverse, fun (A1, A2) -> + A1 ++ A2 + end}, + List, Malt). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> {list(), list()} +partition(Fun, List) -> + partition(Fun, List, 1). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> {list(), list()} +partition(Fun, List, Malt) -> + runmany(fun (L) -> + lists:partition(Fun, L) + end, + {reverse, fun ({True1, False1}, {True2, False2}) -> + {True1 ++ True2, False1 ++ False2} + end}, + List, Malt). + +% SORTMALT needs to be tuned +-define(SORTMALT, 100). + +% @doc Same semantics as in module +% lists. +% @spec (List) -> list() +sort(List) -> + sort(fun (A, B) -> + A =< B + end, + List). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +sort(Fun, List) -> + sort(Fun, List, ?SORTMALT). + +% @doc This version lets you specify your own malt for sort. +% +% sort splits the list into sublists and sorts them, and it merges the +% sorted lists together. These are done in parallel. Each sublist is +% sorted in a seperate process, and each merging of results is done in a +% seperate process. Malt defaults to 100, causing the list to be split into +% 100-element sublists. +% @spec (Fun, List, Malt) -> list() +sort(Fun, List, Malt) -> + Fun2 = fun (L) -> + lists:sort(Fun, L) + end, + Fuse = fun (A1, A2) -> + lists:merge(Fun, A1, A2) + end, + runmany(Fun2, {recursive, Fuse}, List, Malt). + +% @doc Same semantics as in module +% lists. +% @spec (List) -> list() +usort(List) -> + usort(fun (A, B) -> + A =< B + end, + List). + +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +usort(Fun, List) -> + usort(Fun, List, ?SORTMALT). + +% @doc This version lets you specify your own malt for usort. +% +% usort splits the list into sublists and sorts them, and it merges the +% sorted lists together. These are done in parallel. Each sublist is +% sorted in a seperate process, and each merging of results is done in a +% seperate process. Malt defaults to 100, causing the list to be split into +% 100-element sublists. +% +% usort removes duplicate elments while it sorts. +% @spec (Fun, List, Malt) -> list() +usort(Fun, List, Malt) -> + Fun2 = fun (L) -> + lists:usort(Fun, L) + end, + Fuse = fun (A1, A2) -> + lists:umerge(Fun, A1, A2) + end, + runmany(Fun2, {recursive, Fuse}, List, Malt). + +% @doc Like below, assumes default MapMalt of 1. +% @spec (MapFunc, List) -> Dict +% MapFunc = (term()) -> DeepListOfKeyValuePairs +% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} +mapreduce(MapFunc, List) -> + mapreduce(MapFunc, List, 1). + +% Like below, but uses a default reducer that collects all +% {Key, Value} pairs into a +% dict, +% with values {Key, [Value1, Value2...]}. +% This dict is returned as the result. +mapreduce(MapFunc, List, MapMalt) -> + mapreduce(MapFunc, List, dict:new(), fun add_key/3, MapMalt). + +% @doc This is a very basic mapreduce. You won't write a Google-rivaling +% search engine with it. It has no equivalent in lists. Each +% element in the list is run through the MapFunc, which produces either +% a {Key, Value} pair, or a lists of key value pairs, or a list of lists of +% key value pairs...etc. A reducer process runs in parallel with the mapping +% processes, collecting the key value pairs. It starts with a state given by +% InitState, and for each {Key, Value} pair that it receives it invokes +% ReduceFunc(OldState, Key, Value) to compute its new state. mapreduce returns +% the reducer's final state. +% +% MapMalt is the malt for the mapping operation, with a default value of 1, +% meaning each element of the list is mapped by a seperate process. +% +% mapreduce requires OTP R11B, or it may leave monitoring messages in the +% message queue. +% @spec (MapFunc, List, InitState, ReduceFunc, MapMalt) -> Dict +% MapFunc = (term()) -> DeepListOfKeyValuePairs +% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} +% ReduceFunc = (OldState::term(), Key::term(), Value::term() -> NewState::term() +mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> + Parent = self(), + {Reducer, ReducerRef} = + erlang:spawn_monitor(fun () -> + reducer(Parent, 0, InitState, ReduceFunc) + end), + MapFunc2 = fun (L) -> + Reducer ! lists:map(MapFunc, L), + 1 + end, + SentMessages = try runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) + catch + exit:Reason -> + erlang:demonitor(ReducerRef, [flush]), + Reducer ! die, + exit(Reason) + end, + Reducer ! {mappers, done, SentMessages}, + Results = receive + {Reducer, Results2} -> + Results2; + {'DOWN', _, _, Reducer, Reason2} -> + exit(Reason2) + end, + receive + {'DOWN', _, _, Reducer, normal} -> + nil + end, + Results. + +reducer(Parent, NumReceived, State, Func) -> + receive + die -> + nil; + {mappers, done, NumReceived} -> + Parent ! {self (), State}; + Keys -> + reducer(Parent, NumReceived + 1, each_key(State, Func, Keys), Func) + end. + +each_key(State, Func, {Key, Value}) -> + Func(State, Key, Value); +each_key(State, Func, [List|Keys]) -> + each_key(each_key(State, Func, List), Func, Keys); +each_key(State, _, []) -> + State. + +add_key(Dict, Key, Value) -> + case dict:is_key(Key, Dict) of + true -> + dict:append(Key, Value, Dict); + false -> + dict:store(Key, [Value], Dict) + end. + +% @doc Like below, but assumes a Malt of 1, +% meaning each element of the list is processed by a seperate process. +% @spec (Fun, Fuse, List) -> term() +runmany(Fun, Fuse, List) -> + runmany(Fun, Fuse, List, 1). + +% Begin internal stuff (though runmany/4 is exported). + +% @doc All of the other functions are implemented with runmany. runmany +% takes a List, splits it into sublists, and starts processes to operate on +% each sublist, all done according to Malt. Each process passes its sublist +% into Fun and sends the result back. +% +% The results are then fused together to get the final result. There are two +% ways this can operate, lineraly and recursively. If Fuse is a function, +% a fuse is done linearly left-to-right on the sublists, the results +% of processing the first and second sublists being passed to Fuse, then +% the result of the first fuse and processing the third sublits, and so on. If +% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results +% of processing the second-to-last and last sublists being passed to FuseFunc, +% then the results of processing the third-to-last sublist and +% the results of the first fuse, and and so forth. +% Both methods preserve the original order of the lists elements. +% +% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. +% The recursive fuse makes no guarantee about the order the results of +% sublists, or the results of fuses are passed to FuseFunc. It +% continues fusing pairs of results until it is down to one. +% +% Recursive fuse is down in parallel with processing the sublists, and a +% process is spawned to fuse each pair of results. It is a parallized +% algorithm. Linear fuse is done after all results of processing sublists +% have been collected, and can only run in a single process. +% +% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if +% the malt contains {nodes, NodeList} or {processes, X}. If this is not the +% case, a linear fuse is done. +% @spec (Fun, Fuse, List, Malt) -> term() +% Fun = (list()) -> term() +% Fuse = FuseFunc | {recursive, FuseFunc} +% FuseFunc = (term(), term()) -> term() +runmany(Fun, Fuse, List, Malt) when is_list(Malt) -> + runmany(Fun, Fuse, List, local, no_split, Malt); +runmany(Fun, Fuse, List, Malt) -> + runmany(Fun, Fuse, List, [Malt]). + +runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) when is_integer(MaltTerm) -> + runmany(Fun, Fuse, List, Nodes, MaltTerm, Malt); +% run a process for each scheduler +runmany(Fun, Fuse, List, local, Split, [{processes, schedulers}|Malt]) -> + S = erlang:system_info(schedulers), + runmany(Fun, Fuse, List, local, Split, [{processes, S}|Malt]); +% Split the list into X sublists, where X is the number of processes +runmany(Fun, Fuse, List, local, no_split, [{processes, X}|_]=Malt) -> + L = length(List), + case L rem X of + 0 -> + runmany(Fun, Fuse, List, local, L div X, Malt); + _ -> + runmany(Fun, Fuse, List, local, L div X + 1, Malt) + end; +% run X process on local machine +runmany(Fun, Fuse, List, local, Split, [{processes, X}|Malt]) -> + Nodes = lists:duplicate(X, node()), + runmany(Fun, Fuse, List, Nodes, Split, Malt); +runmany(Fun, Fuse, List, Nodes, Split, [{timeout, X}|Malt]) -> + Parent = self(), + Timer = spawn(fun () -> + receive + stoptimer -> + Parent ! {timerstopped, self()} + after X -> + Parent ! {timerrang, self()}, + receive + stoptimer -> + Parent ! {timerstopped, self()} + end + end + end), + Ans = try runmany(Fun, Fuse, List, Nodes, Split, Malt) + catch + % we really just want the after block, the syntax + % makes this catch necessary. + willneverhappen -> + nil + after + Timer ! stoptimer, + cleanup_timer(Timer) + end, + Ans; +runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> + Nodes = lists:foldl(fun ({Node, schedulers}, A) -> + X = schedulers_on_node(Node) + 1, + lists:reverse(lists:duplicate(X, Node), A); + ({Node, X}, A) -> + lists:reverse(lists:duplicate(X, Node), A); + (Node, A) -> + [Node|A] + end, + [], NodeList), + runmany(Fun, Fuse, List, Nodes, Split, Malt); +% local recursive fuse, for when we weren't invoked with {processes, X} +% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. +runmany(Fun, {recursive, Fuse}, List, local, Split, []) -> + runmany(Fun, Fuse, List, local, Split, []); +% by default, operate on each element seperately +runmany(Fun, Fuse, List, Nodes, no_split, []) -> + runmany(Fun, Fuse, List, Nodes, 1, []); +runmany(Fun, Fuse, List, local, Split, []) -> + List2 = splitmany(List, Split), + local_runmany(Fun, Fuse, List2); +runmany(Fun, Fuse, List, Nodes, Split, []) -> + List2 = splitmany(List, Split), + cluster_runmany(Fun, Fuse, List2, Nodes). + +cleanup_timer(Timer) -> + receive + {timerrang, Timer} -> + cleanup_timer(Timer); + {timerstopped, Timer} -> + nil + end. + +schedulers_on_node(Node) -> + case get(plists_schedulers_on_nodes) of + undefined -> + X = determine_schedulers(Node), + put(plists_schedulers_on_nodes, + dict:store(Node, X, dict:new())), + X; + Dict -> + case dict:is_key(Node, Dict) of + true -> + dict:fetch(Node, Dict); + false -> + X = determine_schedulers(Node), + put(plists_schedulers_on_nodes, + dict:store(Node, X, Dict)), + X + end + end. + +determine_schedulers(Node) -> + Parent = self(), + Child = spawn(Node, fun () -> + Parent ! {self(), erlang:system_info(schedulers)} + end), + erlang:monitor(process, Child), + receive + {Child, X} -> + receive + {'DOWN', _, _, Child, _Reason} -> + nil + end, + X; + {'DOWN', _, _, Child, Reason} when Reason =/= normal -> + 0 + end. + +% local runmany, for when we weren't invoked with {processes, X} +% or {nodes, NodeList}. Every sublist is processed in parallel. +local_runmany(Fun, Fuse, List) -> + Parent = self (), + Pids = lists:map(fun (L) -> + F = fun () -> + Parent ! + {self (), Fun(L)} + end, + {Pid, _} = erlang:spawn_monitor(F), + Pid + end, + List), + Answers = try lists:map(fun receivefrom/1, Pids) + catch throw:Message -> + {BadPid, Reason} = Message, + handle_error(BadPid, Reason, Pids) + end, + lists:foreach(fun (Pid) -> + normal_cleanup(Pid) + end, Pids), + fuse(Fuse, Answers). + +receivefrom(Pid) -> + receive + {Pid, R} -> + R; + {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> + throw({BadPid, Reason}); + {timerrang, _} -> + throw({nil, timeout}) + end. + +% Convert List into [{Number, Sublist}] +cluster_runmany(Fun, Fuse, List, Nodes) -> + {List2, _} = lists:foldl(fun (X, {L, Count}) -> + {[{Count, X}|L], Count+1} + end, + {[], 0}, List), + cluster_runmany(Fun, Fuse, List2, Nodes, [], []). + +% Add a pair of results into the TaskList as a fusing task +cluster_runmany(Fun, {recursive, Fuse}, [], Nodes, Running, + [{_, R1}, {_, R2}|Results]) -> + cluster_runmany(Fun, {recursive, Fuse}, [{fuse, R1, R2}], Nodes, + Running, Results); +% recursive fuse done, return result +cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], [{_, Result}]) -> + Result; +% edge case where we are asked to do nothing +cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], []) -> + []; +% We're done, now we just have to [linear] fuse the results +cluster_runmany(_, Fuse, [], _Nodes, [], Results) -> + fuse(Fuse, lists:map(fun ({_, R}) -> R end, + lists:sort(fun ({A, _}, {B, _}) -> + A =< B + end, + lists:reverse(Results)))); +% We have a ready node and a sublist or fuse to be processed, so we start +% a new process +cluster_runmany(Fun, Fuse, [Task|TaskList], [N|Nodes], Running, Results) -> + Parent = self(), + case Task of + {Num, L2} -> + Fun2 = fun () -> + Parent ! {self(), Num, Fun(L2)} + end; + {fuse, R1, R2} -> + {recursive, FuseFunc} = Fuse, + Fun2 = fun () -> + Parent ! {self(), fuse, FuseFunc(R1, R2)} + end + end, + Fun3 = fun () -> + try Fun2() + catch + exit:siblingdied -> + ok; + exit:Reason -> + Parent ! {self(), error, Reason}; + error:R -> + Parent ! {self(), error, {R, erlang:get_stacktrace()}}; + throw:R -> + Parent ! {self(), error, {{nocatch, R}, erlang:get_stacktrace()}} + end + end, + Pid = spawn(N, Fun3), + erlang:monitor(process, Pid), + cluster_runmany(Fun, Fuse, TaskList, Nodes, [{Pid, N, Task}|Running], Results); +% We can't start a new process, but can watch over already running ones +cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Running) > 0 -> + receive + {_Pid, error, Reason} -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(junkvalue, Reason, RunningPids); + {Pid, Num, Result} -> + % throw out the exit message, Reason should be + % normal, noproc, or noconnection + receive {'DOWN', _, _, Pid, _Reason} -> + nil + end, + {Running2, FinishedNode, _} = delete_running(Pid, Running, []), + cluster_runmany(Fun, Fuse, TaskList, + [FinishedNode|Nodes], Running2, [{Num, Result}|Results]); + {timerrang, _} -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(nil, timeout, RunningPids); + % node failure + {'DOWN', _, _, Pid, noconnection} -> + {Running2, _DeadNode, Task} = delete_running(Pid, Running, []), + cluster_runmany(Fun, Fuse, [Task|TaskList], Nodes, + Running2, Results); + % could a noproc exit message come before the message from + % the process? we are assuming it can't. + % this clause is unlikely to get invoked due to cluster_runmany's + % spawned processes. It will still catch errors in mapreduce's + % reduce process, however. + {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(BadPid, Reason, RunningPids) + end; +% We have data, but no nodes either available or occupied +cluster_runmany(_, _, [_Non|_Empty], []=_Nodes, []=_Running, _) -> + exit(allnodescrashed). + +delete_running(Pid, [{Pid, Node, List}|Running], Acc) -> + {Running ++ Acc, Node, List}; +delete_running(Pid, [R|Running], Acc) -> + delete_running(Pid, Running, [R|Acc]). + +handle_error(BadPid, Reason, Pids) -> + lists:foreach(fun (Pid) -> + exit(Pid, siblingdied) + end, Pids), + lists:foreach(fun (Pid) -> + error_cleanup(Pid, BadPid) + end, Pids), + exit(Reason). + +error_cleanup(BadPid, BadPid) -> + ok; +error_cleanup(Pid, BadPid) -> + receive + {Pid, _} -> + error_cleanup(Pid, BadPid); + {Pid, _, _} -> + error_cleanup(Pid, BadPid); + {'DOWN', _, _, Pid, _Reason} -> + ok + end. + +normal_cleanup(Pid) -> + receive + {'DOWN', _, _, Pid, _Reason} -> + ok + end. + +% edge case +fuse(_, []) -> + []; +fuse({reverse, _}=Fuse, Results) -> + [RL|ResultsR] = lists:reverse(Results), + fuse(Fuse, ResultsR, RL); +fuse(Fuse, [R1|Results]) -> + fuse(Fuse, Results, R1). + +fuse({reverse, FuseFunc}=Fuse, [R2|Results], R1) -> + fuse(Fuse, Results, FuseFunc(R2, R1)); +fuse(Fuse, [R2|Results], R1) -> + fuse(Fuse, Results, Fuse(R1, R2)); +fuse(_, [], R) -> + R. + +% Splits a list into a list of sublists, each of size Size, +% except for the last element which is less if the original list +% could not be evenly divided into Size-sized lists. +splitmany(List, Size) -> + splitmany(List, [], Size). + +splitmany([], Acc, _) -> + lists:reverse(Acc); +splitmany(List, Acc, Size) -> + {Top, NList} = split(Size, List), + splitmany(NList, [Top|Acc], Size). + +% Like lists:split, except it splits a list smaller than its first +% parameter +split(Size, List) -> + split(Size, List, []). + +split(0, List, Acc) -> + {lists:reverse(Acc), List}; +split(Size, [H|List], Acc) -> + split(Size - 1, List, [H|Acc]); +split(_, [], Acc) -> + {lists:reverse(Acc), []}. From 31ebca114ade860f2bf665ae6265f3de4b3f2cee Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 11:52:47 -0500 Subject: [PATCH 051/240] replace ec_plists with Stephan's plists Signed-off-by: Jordan Wilberding --- src/ec_plists.erl | 1060 +++++++++++++++++++++++++++++++++++---------- src/plists.erl | 858 ------------------------------------ 2 files changed, 827 insertions(+), 1091 deletions(-) delete mode 100644 src/plists.erl diff --git a/src/ec_plists.erl b/src/ec_plists.erl index cd14697..688d5a5 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -1,264 +1,858 @@ -%%%------------------------------------------------------------------- -%%% @doc -%%% simple parrallel map. Originally provided by Joe Armstrong -%%% on the erlang questions mailing list. -%%% @end -%%%------------------------------------------------------------------- --module(ec_plists). +% @author Stephen Marsh +% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] +% @doc plists is a drop-in replacement for module +% lists, +% making most list operations parallel. It can operate on each element in +% parallel, for IO-bound operations, on sublists in parallel, for +% taking advantage of multi-core machines with CPU-bound operations, and +% across erlang nodes, for parallizing inside a cluster. It handles +% errors and node failures. It can be configured, tuned, and tweaked to +% get optimal performance while minimizing overhead. +% +% Almost all the functions are +% identical to equivalent functions in lists, returning exactly the same +% result, and having both a form with an identical syntax that operates on +% each element in parallel and a form which takes an optional "malt", +% a specification for how to parallize the operation. +% +% fold is the one exception, parallel fold is different from linear fold. +% This module also include a simple mapreduce implementation, and the +% function runmany. All the other functions are implemented with runmany, +% which is as a generalization of parallel list operations. +% +% == Malts == +% A malt specifies how to break a list into sublists, and can optionally +% specify a timeout, which nodes to run on, and how many processes to start +% per node. +% +% Malt = MaltComponent | [MaltComponent]
+% MaltComponent = SubListSize::integer() | {processes, integer()} | +% {processes, schedulers} | +% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
+% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | +% {Node::atom(), schedulers} +% +% An integer can be given to specify the exact size for +% sublists. 1 is a good choice for IO-bound operations and when +% the operation on each list element is expensive. Larger numbers +% minimize overhead and are faster for cheap operations. +% +% If the integer is omitted, and +% you have specified a {processes, X}, the list is +% split into X sublists. This is only +% useful when the time to process each element is close to identical and you +% know exactly how many lines of execution are available to you. +% +% If neither of the above applies, the sublist size defaults to 1. +% +% You can use {processes, X} to have the list processed +% by X processes on the local machine. A good choice for X is the number of +% lines of execution (cores) the machine provides. This can be done +% automatically with {processes, schedulers}, which sets +% the number of processes to the number of schedulers in the erlang virtual +% machine (probably equal to the number of cores). +% +% {timeout, Milliseconds} specifies a timeout. This is a timeout for the entire +% operation, both operating on the sublists and combining the results. +% exit(timeout) is evaluated if the timeout is exceeded. +% +% {nodes, NodeList} specifies that the operation should be done across nodes. +% Every element of NodeList is of the form {NodeName, NumProcesses} or +% NodeName, which means the same as {NodeName, 1}. plists runs +% NumProcesses processes on NodeName concurrently. A good choice for +% NumProcesses is the number of lines of execution (cores) a node provides +% plus one. This ensures the node is completely busy even when +% fetching a new sublist. This can be done automatically with +% {NodeName, schedulers}, in which case +% plists uses a cached value if it has one, and otherwise finds the number of +% schedulers in the remote node and adds one. This will ensure at least one +% busy process per core (assuming the node has a scheduler for each core). +% +% plists is able to recover if a node goes down. +% If all nodes go down, exit(allnodescrashed) is evaluated. +% +% Any of the above may be used as a malt, or may be combined into a list. +% {nodes, NodeList} and {processes, X} may not be combined. +% +% === Examples === +% % start a process for each element (1-element sublists)
+% 1 +% +% % start a process for each ten elements (10-element sublists)
+% 10 +% +% % split the list into two sublists and process in two processes
+% {processes, 2} +% +% % split the list into X sublists and process in X processes,
+% % where X is the number of cores in the machine
+% {processes, schedulers} +% +% % split the list into 10-element sublists and process in two processes
+% [10, {processes, 2}] +% +% % timeout after one second. Assumes that a process should be started
+% % for each element.
+% {timeout, 1000} +% +% % Runs 3 processes at a time on apple@desktop, +% and 2 on orange@laptop
+% % This is the best way to utilize all the CPU-power of a dual-core
+% % desktop and a single-core laptop. Assumes that the list should be
+% % split into 1-element sublists.
+% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} +% +% Like above, but makes plists figure out how many processes to use. +% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} +% +% % Gives apple and orange three seconds to process the list as
+% % 100-element sublists.
+% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] +% +% === Aside: Why Malt? === +% I needed a word for this concept, so maybe my subconsciousness gave me one by +% making me misspell multiply. Maybe it is an acronym for Malt is A List +% Tearing Specification. Maybe it is a beer metaphor, suggesting that code +% only runs in parallel if bribed with spirits. It's jargon, learn it +% or you can't be part of the in-group. +% +% == Messages and Errors == +% plists assures that no extraneous messages are left in or will later +% enter the message queue. This is guaranteed even in the event of an error. +% +% Errors in spawned processes are caught and propagated to the calling +% process. If you invoke +% +% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). +% +% you get a badarith error, exactly like when you use lists:map. +% +% plists uses monitors to watch the processes it spawns. It is not a good idea +% to invoke plists when you are already monitoring processes. If one of them +% does a non-normal exit, plists receives the 'DOWN' message believing it to be +% from one of its own processes. The error propagation system goes into +% effect, which results in the error occuring in the calling process. +% +% == License == +% The MIT License +% +% Copyright (c) 2007 Stephen Marsh +% +% Permission is hereby granted, free of charge, to any person obtaining a copy +% of this software and associated documentation files (the "Software"), to deal +% in the Software without restriction, including without limitation the rights +% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +% copies of the Software, and to permit persons to whom the Software is +% furnished to do so, subject to the following conditions: +% +% The above copyright notice and this permission notice shall be included in +% all copies or substantial portions of the Software. +% +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +% THE SOFTWARE. --export([map/2, - map/3, - ftmap/2, - ftmap/3, - filter/2, - filter/3]). --export_type([thunk/0]). +-module(plists). +-export([all/2, all/3, any/2, any/3, filter/2, filter/3, +fold/3, fold/4, fold/5, foreach/2, foreach/3, map/2, map/3, +partition/2, partition/3, sort/1, sort/2, sort/3, +usort/1, usort/2, usort/3, mapreduce/2, mapreduce/3, mapreduce/5, +runmany/3, runmany/4]). -%%============================================================================= -%% Types -%%============================================================================= --type thunk() :: fun((any()) -> any()). +% Everything here is defined in terms of runmany. +% The following methods are convient interfaces to runmany. -%%============================================================================= -%% Public API -%%============================================================================= +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> bool() +all(Fun, List) -> + all(Fun, List, 1). -%% @doc Takes a function and produces a list of the result of the function -%% applied to each element of the argument list. A timeout is optional. -%% In the event of a timeout or an exception the entire map will fail -%% with an excption with class throw. --spec map(fun(), [any()]) -> [any()]. -map(Fun, List) -> - map(Fun, List, infinity). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> bool() +all(Fun, List, Malt) -> + try runmany(fun (L) -> + B = lists:all(Fun, L), + if B -> + nil; + true -> + exit(notall) + end + end, + fun (_A1, _A2) -> + nil + end, + List, Malt) of + _ -> + true + catch exit:notall -> + false + end. --spec map(thunk(), [any()], timeout() | infinity) -> [any()]. -map(Fun, List, Timeout) -> - run_list_fun_in_parallel(map, Fun, List, Timeout). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> bool() +any(Fun, List) -> + any(Fun, List, 1). -%% @doc Takes a function and produces a list of the result of the function -%% applied to each element of the argument list. A timeout is optional. -%% This function differes from regular map in that it is fault tolerant. -%% If a timeout or an exception occurs while processing an element in -%% the input list the ftmap operation will continue to function. Timeouts -%% and exceptions will be reflected in the output of this function. -%% All application level results are wrapped in a tuple with the tag -%% 'value'. Exceptions will come through as they are and timeouts will -%% return as the atom timeout. -%% This is useful when the ftmap is being used for side effects. -%%
-%% 2> ftmap(fun(N) -> factorial(N) end, [1, 2, 1000000, "not num"], 100)
-%% [{value, 1}, {value, 2}, timeout, {badmatch, ...}]
-%% 
--spec ftmap(thunk(), [any()]) -> [{value, any()} | any()]. -ftmap(Fun, List) -> - ftmap(Fun, List, infinity). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> bool() +any(Fun, List, Malt) -> + try runmany(fun (L) -> + B = lists:any(Fun, L), + if B -> + exit(any); + true -> + nil + end + end, + fun (_A1, _A2) -> + nil + end, + List, Malt) of + _ -> + false + catch exit:any -> + true + end. --spec ftmap(thunk(), [any()], timeout() | infinity) -> [{value, any()} | any()]. -ftmap(Fun, List, Timeout) -> - run_list_fun_in_parallel(ftmap, Fun, List, Timeout). - -%% @doc Returns a list of the elements in the supplied list which -%% the function Fun returns true. A timeout is optional. In the -%% event of a timeout the filter operation fails. --spec filter(thunk(), [any()]) -> [any()]. +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() filter(Fun, List) -> - filter(Fun, List, infinity). + filter(Fun, List, 1). --spec filter(thunk(), [any()], timeout() | infinity) -> [any()]. -filter(Fun, List, Timeout) -> - run_list_fun_in_parallel(filter, Fun, List, Timeout). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> list() +filter(Fun, List, Malt) -> + runmany(fun (L) -> + lists:filter(Fun, L) + end, + {reverse, fun (A1, A2) -> + A1 ++ A2 + end}, + List, Malt). -%%============================================================================= -%% Internal API -%%============================================================================= --spec run_list_fun_in_parallel(atom(), thunk(), [any()], timeout() | infinity) -> [any()]. -run_list_fun_in_parallel(ListFun, Fun, List, Timeout) -> - LocalPid = self(), - Pids = - lists:map(fun(E) -> - Pid = - proc_lib:spawn(fun() -> - wait(LocalPid, Fun, - E, Timeout) - end), - {Pid, E} - end, List), - gather(ListFun, Pids). +% Note that with parallel fold there is not foldl and foldr, +% instead just one fold that can fuse Accumlators. --spec wait(pid(), thunk(), any(), timeout() | infinity) -> any(). -wait(Parent, Fun, E, Timeout) -> - WaitPid = self(), - Child = spawn(fun() -> - do_f(WaitPid, Fun, E) - end), +% @doc Like below, but assumes 1 as the Malt. This function is almost useless, +% and is intended only to aid converting code from using lists to plists. +% @spec (Fun, InitAcc, List) -> term() +fold(Fun, InitAcc, List) -> + fold(Fun, Fun, InitAcc, List, 1). - wait(Parent, Child, Timeout). +% @doc Like below, but uses the Fun as the Fuse by default. +% @spec (Fun, InitAcc, List, Malt) -> term() +fold(Fun, InitAcc, List, Malt) -> + fold(Fun, Fun, InitAcc, List, Malt). --spec wait(pid(), pid(), timeout() | infinity) -> any(). -wait(Parent, Child, Timeout) -> - receive - {Child, Ret} -> - Parent ! {self(), Ret} - after Timeout -> - exit(Child, timeout), - Parent ! {self(), timeout} - end. +% @doc fold is more complex when made parallel. There is no foldl and foldr, +% accumulators aren't passed in any defined order. +% The list is split into sublists which are folded together. Fun is +% identical to the function passed to lists:fold[lr], it takes +% (an element, and the accumulator) and returns -> a new accumulator. +% It is used for the initial stage of folding sublists. Fuse fuses together +% the results, it takes (Results1, Result2) and returns -> a new result. +% By default sublists are fused left to right, each result of a fuse being +% fed into the first element of the next fuse. The result of the last fuse +% is the result. +% +% Fusing may also run in parallel using a recursive algorithm, +% by specifying the fuse as {recursive, Fuse}. See +% the discussion in {@link runmany/4}. +% +% Malt is the malt for the initial folding of sublists, and for the +% possible recursive fuse. +% @spec (Fun, Fuse, InitAcc, List, Malt) -> term() +fold(Fun, Fuse, InitAcc, List, Malt) -> + Fun2 = fun (L) -> lists:foldl(Fun, InitAcc, L) end, + runmany(Fun2, Fuse, List, Malt). --spec gather(atom(), [any()]) -> [any()]. -gather(map, PidElementList) -> - map_gather(PidElementList); -gather(ftmap, PidElementList) -> - ftmap_gather(PidElementList); -gather(filter, PidElementList) -> - filter_gather(PidElementList). +% @doc Similiar to foreach in module +% lists +% except it makes no guarantee about the order it processes list elements. +% @spec (Fun, List) -> void() +foreach(Fun, List) -> + foreach(Fun, List, 1). --spec map_gather([pid()]) -> [any()]. -map_gather([{Pid, _E} | Rest]) -> - receive - {Pid, {value, Ret}} -> - [Ret|map_gather(Rest)]; - %% timeouts fall here too. Should timeouts be a return value - %% or an exception? I lean toward return value, but the code - %% is easier with the exception. Thoughts? - {Pid, Exception} -> - killall(Rest), - throw(Exception) - end; -map_gather([]) -> - []. +% @doc Similiar to foreach in module +% lists +% except it makes no guarantee about the order it processes list elements. +% @spec (Fun, List, Malt) -> void() +foreach(Fun, List, Malt) -> + runmany(fun (L) -> + lists:foreach(Fun, L) + end, + fun (_A1, _A2) -> + ok + end, + List, Malt). --spec ftmap_gather([pid()]) -> [any()]. -ftmap_gather([{Pid, _E} | Rest]) -> - receive - {Pid, Value} -> [Value|ftmap_gather(Rest)] - end; -ftmap_gather([]) -> - []. +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +map(Fun, List) -> + map(Fun, List, 1). --spec filter_gather([pid()]) -> [any()]. -filter_gather([{Pid, E} | Rest]) -> - receive - {Pid, {value, false}} -> - filter_gather(Rest); - {Pid, {value, true}} -> - [E|filter_gather(Rest)]; - {Pid, {value, NotBool}} -> - killall(Rest), - throw({bad_return_value, NotBool}); - {Pid, Exception} -> - killall(Rest), - throw(Exception) - end; -filter_gather([]) -> - []. +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> list() +map(Fun, List, Malt) -> + runmany(fun (L) -> + lists:map(Fun, L) + end, + {reverse, fun (A1, A2) -> + A1 ++ A2 + end}, + List, Malt). --spec do_f(pid(), thunk(), any()) -> no_return(). -do_f(Parent, F, E) -> - try - Result = F(E), - Parent ! {self(), {value, Result}} - catch - _Class:Exception -> - %% Losing class info here, but since throw does not accept - %% that arg anyhow and forces a class of throw it does not - %% matter. - Parent ! {self(), Exception} - end. +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> {list(), list()} +partition(Fun, List) -> + partition(Fun, List, 1). --spec killall([pid()]) -> ok. -killall([{Pid, _E}|T]) -> - exit(Pid, kill), - killall(T); -killall([]) -> - ok. +% @doc Same semantics as in module +% lists. +% @spec (Fun, List, Malt) -> {list(), list()} +partition(Fun, List, Malt) -> + runmany(fun (L) -> + lists:partition(Fun, L) + end, + {reverse, fun ({True1, False1}, {True2, False2}) -> + {True1 ++ True2, False1 ++ False2} + end}, + List, Malt). -%%============================================================================= -%% Tests -%%============================================================================= +% SORTMALT needs to be tuned +-define(SORTMALT, 100). --ifndef(NOTEST). --include_lib("eunit/include/eunit.hrl"). +% @doc Same semantics as in module +% lists. +% @spec (List) -> list() +sort(List) -> + sort(fun (A, B) -> + A =< B + end, + List). -map_good_test() -> - Results = map(fun(_) -> - ok - end, - lists:seq(1, 5), infinity), - ?assertMatch([ok, ok, ok, ok, ok], - Results). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +sort(Fun, List) -> + sort(Fun, List, ?SORTMALT). -ftmap_good_test() -> - Results = ftmap(fun(_) -> - ok - end, - lists:seq(1, 3), infinity), - ?assertMatch([{value, ok}, {value, ok}, {value, ok}], - Results). +% @doc This version lets you specify your own malt for sort. +% +% sort splits the list into sublists and sorts them, and it merges the +% sorted lists together. These are done in parallel. Each sublist is +% sorted in a seperate process, and each merging of results is done in a +% seperate process. Malt defaults to 100, causing the list to be split into +% 100-element sublists. +% @spec (Fun, List, Malt) -> list() +sort(Fun, List, Malt) -> + Fun2 = fun (L) -> + lists:sort(Fun, L) + end, + Fuse = fun (A1, A2) -> + lists:merge(Fun, A1, A2) + end, + runmany(Fun2, {recursive, Fuse}, List, Malt). -filter_good_test() -> - Results = filter(fun(X) -> - X == show - end, - [show, show, remove], infinity), - ?assertMatch([show, show], - Results). +% @doc Same semantics as in module +% lists. +% @spec (List) -> list() +usort(List) -> + usort(fun (A, B) -> + A =< B + end, + List). -map_timeout_test() -> - Results = - try - map(fun(T) -> - timer:sleep(T), - T - end, - [1, 100], 10) - catch - C:E -> {C, E} - end, - ?assertMatch({throw, timeout}, Results). +% @doc Same semantics as in module +% lists. +% @spec (Fun, List) -> list() +usort(Fun, List) -> + usort(Fun, List, ?SORTMALT). -ftmap_timeout_test() -> - Results = ftmap(fun(X) -> - timer:sleep(X), - true - end, - [100, 1], 10), - ?assertMatch([timeout, {value, true}], Results). +% @doc This version lets you specify your own malt for usort. +% +% usort splits the list into sublists and sorts them, and it merges the +% sorted lists together. These are done in parallel. Each sublist is +% sorted in a seperate process, and each merging of results is done in a +% seperate process. Malt defaults to 100, causing the list to be split into +% 100-element sublists. +% +% usort removes duplicate elments while it sorts. +% @spec (Fun, List, Malt) -> list() +usort(Fun, List, Malt) -> + Fun2 = fun (L) -> + lists:usort(Fun, L) + end, + Fuse = fun (A1, A2) -> + lists:umerge(Fun, A1, A2) + end, + runmany(Fun2, {recursive, Fuse}, List, Malt). -filter_timeout_test() -> - Results = - try - filter(fun(T) -> - timer:sleep(T), - T == 1 +% @doc Like below, assumes default MapMalt of 1. +% @spec (MapFunc, List) -> Dict +% MapFunc = (term()) -> DeepListOfKeyValuePairs +% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} +mapreduce(MapFunc, List) -> + mapreduce(MapFunc, List, 1). + +% Like below, but uses a default reducer that collects all +% {Key, Value} pairs into a +% dict, +% with values {Key, [Value1, Value2...]}. +% This dict is returned as the result. +mapreduce(MapFunc, List, MapMalt) -> + mapreduce(MapFunc, List, dict:new(), fun add_key/3, MapMalt). + +% @doc This is a very basic mapreduce. You won't write a Google-rivaling +% search engine with it. It has no equivalent in lists. Each +% element in the list is run through the MapFunc, which produces either +% a {Key, Value} pair, or a lists of key value pairs, or a list of lists of +% key value pairs...etc. A reducer process runs in parallel with the mapping +% processes, collecting the key value pairs. It starts with a state given by +% InitState, and for each {Key, Value} pair that it receives it invokes +% ReduceFunc(OldState, Key, Value) to compute its new state. mapreduce returns +% the reducer's final state. +% +% MapMalt is the malt for the mapping operation, with a default value of 1, +% meaning each element of the list is mapped by a seperate process. +% +% mapreduce requires OTP R11B, or it may leave monitoring messages in the +% message queue. +% @spec (MapFunc, List, InitState, ReduceFunc, MapMalt) -> Dict +% MapFunc = (term()) -> DeepListOfKeyValuePairs +% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} +% ReduceFunc = (OldState::term(), Key::term(), Value::term() -> NewState::term() +mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> + Parent = self(), + {Reducer, ReducerRef} = + erlang:spawn_monitor(fun () -> + reducer(Parent, 0, InitState, ReduceFunc) + end), + MapFunc2 = fun (L) -> + Reducer ! lists:map(MapFunc, L), + 1 + end, + SentMessages = try runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) + catch + exit:Reason -> + erlang:demonitor(ReducerRef, [flush]), + Reducer ! die, + exit(Reason) end, - [1, 100], 10) - catch - C:E -> {C, E} - end, - ?assertMatch({throw, timeout}, Results). - -map_bad_test() -> - Results = - try - map(fun(_) -> - throw(test_exception) - end, - lists:seq(1, 5), infinity) - catch - C:E -> {C, E} - end, - ?assertMatch({throw, test_exception}, Results). - -ftmap_bad_test() -> - Results = - ftmap(fun(2) -> - throw(test_exception); - (N) -> - N + Reducer ! {mappers, done, SentMessages}, + Results = receive + {Reducer, Results2} -> + Results2; + {'DOWN', _, _, Reducer, Reason2} -> + exit(Reason2) end, - lists:seq(1, 5), infinity), - ?assertMatch([{value, 1}, test_exception, {value, 3}, - {value, 4}, {value, 5}] , Results). + receive + {'DOWN', _, _, Reducer, normal} -> + nil + end, + Results. --endif. +reducer(Parent, NumReceived, State, Func) -> + receive + die -> + nil; + {mappers, done, NumReceived} -> + Parent ! {self (), State}; + Keys -> + reducer(Parent, NumReceived + 1, each_key(State, Func, Keys), Func) + end. + +each_key(State, Func, {Key, Value}) -> + Func(State, Key, Value); +each_key(State, Func, [List|Keys]) -> + each_key(each_key(State, Func, List), Func, Keys); +each_key(State, _, []) -> + State. + +add_key(Dict, Key, Value) -> + case dict:is_key(Key, Dict) of + true -> + dict:append(Key, Value, Dict); + false -> + dict:store(Key, [Value], Dict) + end. + +% @doc Like below, but assumes a Malt of 1, +% meaning each element of the list is processed by a seperate process. +% @spec (Fun, Fuse, List) -> term() +runmany(Fun, Fuse, List) -> + runmany(Fun, Fuse, List, 1). + +% Begin internal stuff (though runmany/4 is exported). + +% @doc All of the other functions are implemented with runmany. runmany +% takes a List, splits it into sublists, and starts processes to operate on +% each sublist, all done according to Malt. Each process passes its sublist +% into Fun and sends the result back. +% +% The results are then fused together to get the final result. There are two +% ways this can operate, lineraly and recursively. If Fuse is a function, +% a fuse is done linearly left-to-right on the sublists, the results +% of processing the first and second sublists being passed to Fuse, then +% the result of the first fuse and processing the third sublits, and so on. If +% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results +% of processing the second-to-last and last sublists being passed to FuseFunc, +% then the results of processing the third-to-last sublist and +% the results of the first fuse, and and so forth. +% Both methods preserve the original order of the lists elements. +% +% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. +% The recursive fuse makes no guarantee about the order the results of +% sublists, or the results of fuses are passed to FuseFunc. It +% continues fusing pairs of results until it is down to one. +% +% Recursive fuse is down in parallel with processing the sublists, and a +% process is spawned to fuse each pair of results. It is a parallized +% algorithm. Linear fuse is done after all results of processing sublists +% have been collected, and can only run in a single process. +% +% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if +% the malt contains {nodes, NodeList} or {processes, X}. If this is not the +% case, a linear fuse is done. +% @spec (Fun, Fuse, List, Malt) -> term() +% Fun = (list()) -> term() +% Fuse = FuseFunc | {recursive, FuseFunc} +% FuseFunc = (term(), term()) -> term() +runmany(Fun, Fuse, List, Malt) when is_list(Malt) -> + runmany(Fun, Fuse, List, local, no_split, Malt); +runmany(Fun, Fuse, List, Malt) -> + runmany(Fun, Fuse, List, [Malt]). + +runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) when is_integer(MaltTerm) -> + runmany(Fun, Fuse, List, Nodes, MaltTerm, Malt); +% run a process for each scheduler +runmany(Fun, Fuse, List, local, Split, [{processes, schedulers}|Malt]) -> + S = erlang:system_info(schedulers), + runmany(Fun, Fuse, List, local, Split, [{processes, S}|Malt]); +% Split the list into X sublists, where X is the number of processes +runmany(Fun, Fuse, List, local, no_split, [{processes, X}|_]=Malt) -> + L = length(List), + case L rem X of + 0 -> + runmany(Fun, Fuse, List, local, L div X, Malt); + _ -> + runmany(Fun, Fuse, List, local, L div X + 1, Malt) + end; +% run X process on local machine +runmany(Fun, Fuse, List, local, Split, [{processes, X}|Malt]) -> + Nodes = lists:duplicate(X, node()), + runmany(Fun, Fuse, List, Nodes, Split, Malt); +runmany(Fun, Fuse, List, Nodes, Split, [{timeout, X}|Malt]) -> + Parent = self(), + Timer = spawn(fun () -> + receive + stoptimer -> + Parent ! {timerstopped, self()} + after X -> + Parent ! {timerrang, self()}, + receive + stoptimer -> + Parent ! {timerstopped, self()} + end + end + end), + Ans = try runmany(Fun, Fuse, List, Nodes, Split, Malt) + catch + % we really just want the after block, the syntax + % makes this catch necessary. + willneverhappen -> + nil + after + Timer ! stoptimer, + cleanup_timer(Timer) + end, + Ans; +runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> + Nodes = lists:foldl(fun ({Node, schedulers}, A) -> + X = schedulers_on_node(Node) + 1, + lists:reverse(lists:duplicate(X, Node), A); + ({Node, X}, A) -> + lists:reverse(lists:duplicate(X, Node), A); + (Node, A) -> + [Node|A] + end, + [], NodeList), + runmany(Fun, Fuse, List, Nodes, Split, Malt); +% local recursive fuse, for when we weren't invoked with {processes, X} +% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. +runmany(Fun, {recursive, Fuse}, List, local, Split, []) -> + runmany(Fun, Fuse, List, local, Split, []); +% by default, operate on each element seperately +runmany(Fun, Fuse, List, Nodes, no_split, []) -> + runmany(Fun, Fuse, List, Nodes, 1, []); +runmany(Fun, Fuse, List, local, Split, []) -> + List2 = splitmany(List, Split), + local_runmany(Fun, Fuse, List2); +runmany(Fun, Fuse, List, Nodes, Split, []) -> + List2 = splitmany(List, Split), + cluster_runmany(Fun, Fuse, List2, Nodes). + +cleanup_timer(Timer) -> + receive + {timerrang, Timer} -> + cleanup_timer(Timer); + {timerstopped, Timer} -> + nil + end. + +schedulers_on_node(Node) -> + case get(plists_schedulers_on_nodes) of + undefined -> + X = determine_schedulers(Node), + put(plists_schedulers_on_nodes, + dict:store(Node, X, dict:new())), + X; + Dict -> + case dict:is_key(Node, Dict) of + true -> + dict:fetch(Node, Dict); + false -> + X = determine_schedulers(Node), + put(plists_schedulers_on_nodes, + dict:store(Node, X, Dict)), + X + end + end. + +determine_schedulers(Node) -> + Parent = self(), + Child = spawn(Node, fun () -> + Parent ! {self(), erlang:system_info(schedulers)} + end), + erlang:monitor(process, Child), + receive + {Child, X} -> + receive + {'DOWN', _, _, Child, _Reason} -> + nil + end, + X; + {'DOWN', _, _, Child, Reason} when Reason =/= normal -> + 0 + end. + +% local runmany, for when we weren't invoked with {processes, X} +% or {nodes, NodeList}. Every sublist is processed in parallel. +local_runmany(Fun, Fuse, List) -> + Parent = self (), + Pids = lists:map(fun (L) -> + F = fun () -> + Parent ! + {self (), Fun(L)} + end, + {Pid, _} = erlang:spawn_monitor(F), + Pid + end, + List), + Answers = try lists:map(fun receivefrom/1, Pids) + catch throw:Message -> + {BadPid, Reason} = Message, + handle_error(BadPid, Reason, Pids) + end, + lists:foreach(fun (Pid) -> + normal_cleanup(Pid) + end, Pids), + fuse(Fuse, Answers). + +receivefrom(Pid) -> + receive + {Pid, R} -> + R; + {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> + throw({BadPid, Reason}); + {timerrang, _} -> + throw({nil, timeout}) + end. + +% Convert List into [{Number, Sublist}] +cluster_runmany(Fun, Fuse, List, Nodes) -> + {List2, _} = lists:foldl(fun (X, {L, Count}) -> + {[{Count, X}|L], Count+1} + end, + {[], 0}, List), + cluster_runmany(Fun, Fuse, List2, Nodes, [], []). + +% Add a pair of results into the TaskList as a fusing task +cluster_runmany(Fun, {recursive, Fuse}, [], Nodes, Running, + [{_, R1}, {_, R2}|Results]) -> + cluster_runmany(Fun, {recursive, Fuse}, [{fuse, R1, R2}], Nodes, + Running, Results); +% recursive fuse done, return result +cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], [{_, Result}]) -> + Result; +% edge case where we are asked to do nothing +cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], []) -> + []; +% We're done, now we just have to [linear] fuse the results +cluster_runmany(_, Fuse, [], _Nodes, [], Results) -> + fuse(Fuse, lists:map(fun ({_, R}) -> R end, + lists:sort(fun ({A, _}, {B, _}) -> + A =< B + end, + lists:reverse(Results)))); +% We have a ready node and a sublist or fuse to be processed, so we start +% a new process +cluster_runmany(Fun, Fuse, [Task|TaskList], [N|Nodes], Running, Results) -> + Parent = self(), + case Task of + {Num, L2} -> + Fun2 = fun () -> + Parent ! {self(), Num, Fun(L2)} + end; + {fuse, R1, R2} -> + {recursive, FuseFunc} = Fuse, + Fun2 = fun () -> + Parent ! {self(), fuse, FuseFunc(R1, R2)} + end + end, + Fun3 = fun () -> + try Fun2() + catch + exit:siblingdied -> + ok; + exit:Reason -> + Parent ! {self(), error, Reason}; + error:R -> + Parent ! {self(), error, {R, erlang:get_stacktrace()}}; + throw:R -> + Parent ! {self(), error, {{nocatch, R}, erlang:get_stacktrace()}} + end + end, + Pid = spawn(N, Fun3), + erlang:monitor(process, Pid), + cluster_runmany(Fun, Fuse, TaskList, Nodes, [{Pid, N, Task}|Running], Results); +% We can't start a new process, but can watch over already running ones +cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Running) > 0 -> + receive + {_Pid, error, Reason} -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(junkvalue, Reason, RunningPids); + {Pid, Num, Result} -> + % throw out the exit message, Reason should be + % normal, noproc, or noconnection + receive {'DOWN', _, _, Pid, _Reason} -> + nil + end, + {Running2, FinishedNode, _} = delete_running(Pid, Running, []), + cluster_runmany(Fun, Fuse, TaskList, + [FinishedNode|Nodes], Running2, [{Num, Result}|Results]); + {timerrang, _} -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(nil, timeout, RunningPids); + % node failure + {'DOWN', _, _, Pid, noconnection} -> + {Running2, _DeadNode, Task} = delete_running(Pid, Running, []), + cluster_runmany(Fun, Fuse, [Task|TaskList], Nodes, + Running2, Results); + % could a noproc exit message come before the message from + % the process? we are assuming it can't. + % this clause is unlikely to get invoked due to cluster_runmany's + % spawned processes. It will still catch errors in mapreduce's + % reduce process, however. + {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> + RunningPids = lists:map(fun ({Pid, _, _}) -> + Pid + end, + Running), + handle_error(BadPid, Reason, RunningPids) + end; +% We have data, but no nodes either available or occupied +cluster_runmany(_, _, [_Non|_Empty], []=_Nodes, []=_Running, _) -> + exit(allnodescrashed). + +delete_running(Pid, [{Pid, Node, List}|Running], Acc) -> + {Running ++ Acc, Node, List}; +delete_running(Pid, [R|Running], Acc) -> + delete_running(Pid, Running, [R|Acc]). + +handle_error(BadPid, Reason, Pids) -> + lists:foreach(fun (Pid) -> + exit(Pid, siblingdied) + end, Pids), + lists:foreach(fun (Pid) -> + error_cleanup(Pid, BadPid) + end, Pids), + exit(Reason). + +error_cleanup(BadPid, BadPid) -> + ok; +error_cleanup(Pid, BadPid) -> + receive + {Pid, _} -> + error_cleanup(Pid, BadPid); + {Pid, _, _} -> + error_cleanup(Pid, BadPid); + {'DOWN', _, _, Pid, _Reason} -> + ok + end. + +normal_cleanup(Pid) -> + receive + {'DOWN', _, _, Pid, _Reason} -> + ok + end. + +% edge case +fuse(_, []) -> + []; +fuse({reverse, _}=Fuse, Results) -> + [RL|ResultsR] = lists:reverse(Results), + fuse(Fuse, ResultsR, RL); +fuse(Fuse, [R1|Results]) -> + fuse(Fuse, Results, R1). + +fuse({reverse, FuseFunc}=Fuse, [R2|Results], R1) -> + fuse(Fuse, Results, FuseFunc(R2, R1)); +fuse(Fuse, [R2|Results], R1) -> + fuse(Fuse, Results, Fuse(R1, R2)); +fuse(_, [], R) -> + R. + +% Splits a list into a list of sublists, each of size Size, +% except for the last element which is less if the original list +% could not be evenly divided into Size-sized lists. +splitmany(List, Size) -> + splitmany(List, [], Size). + +splitmany([], Acc, _) -> + lists:reverse(Acc); +splitmany(List, Acc, Size) -> + {Top, NList} = split(Size, List), + splitmany(NList, [Top|Acc], Size). + +% Like lists:split, except it splits a list smaller than its first +% parameter +split(Size, List) -> + split(Size, List, []). + +split(0, List, Acc) -> + {lists:reverse(Acc), List}; +split(Size, [H|List], Acc) -> + split(Size - 1, List, [H|Acc]); +split(_, [], Acc) -> + {lists:reverse(Acc), []}. diff --git a/src/plists.erl b/src/plists.erl deleted file mode 100644 index 688d5a5..0000000 --- a/src/plists.erl +++ /dev/null @@ -1,858 +0,0 @@ -% @author Stephen Marsh -% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] -% @doc plists is a drop-in replacement for module -% lists, -% making most list operations parallel. It can operate on each element in -% parallel, for IO-bound operations, on sublists in parallel, for -% taking advantage of multi-core machines with CPU-bound operations, and -% across erlang nodes, for parallizing inside a cluster. It handles -% errors and node failures. It can be configured, tuned, and tweaked to -% get optimal performance while minimizing overhead. -% -% Almost all the functions are -% identical to equivalent functions in lists, returning exactly the same -% result, and having both a form with an identical syntax that operates on -% each element in parallel and a form which takes an optional "malt", -% a specification for how to parallize the operation. -% -% fold is the one exception, parallel fold is different from linear fold. -% This module also include a simple mapreduce implementation, and the -% function runmany. All the other functions are implemented with runmany, -% which is as a generalization of parallel list operations. -% -% == Malts == -% A malt specifies how to break a list into sublists, and can optionally -% specify a timeout, which nodes to run on, and how many processes to start -% per node. -% -% Malt = MaltComponent | [MaltComponent]
-% MaltComponent = SubListSize::integer() | {processes, integer()} | -% {processes, schedulers} | -% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
-% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | -% {Node::atom(), schedulers} -% -% An integer can be given to specify the exact size for -% sublists. 1 is a good choice for IO-bound operations and when -% the operation on each list element is expensive. Larger numbers -% minimize overhead and are faster for cheap operations. -% -% If the integer is omitted, and -% you have specified a {processes, X}, the list is -% split into X sublists. This is only -% useful when the time to process each element is close to identical and you -% know exactly how many lines of execution are available to you. -% -% If neither of the above applies, the sublist size defaults to 1. -% -% You can use {processes, X} to have the list processed -% by X processes on the local machine. A good choice for X is the number of -% lines of execution (cores) the machine provides. This can be done -% automatically with {processes, schedulers}, which sets -% the number of processes to the number of schedulers in the erlang virtual -% machine (probably equal to the number of cores). -% -% {timeout, Milliseconds} specifies a timeout. This is a timeout for the entire -% operation, both operating on the sublists and combining the results. -% exit(timeout) is evaluated if the timeout is exceeded. -% -% {nodes, NodeList} specifies that the operation should be done across nodes. -% Every element of NodeList is of the form {NodeName, NumProcesses} or -% NodeName, which means the same as {NodeName, 1}. plists runs -% NumProcesses processes on NodeName concurrently. A good choice for -% NumProcesses is the number of lines of execution (cores) a node provides -% plus one. This ensures the node is completely busy even when -% fetching a new sublist. This can be done automatically with -% {NodeName, schedulers}, in which case -% plists uses a cached value if it has one, and otherwise finds the number of -% schedulers in the remote node and adds one. This will ensure at least one -% busy process per core (assuming the node has a scheduler for each core). -% -% plists is able to recover if a node goes down. -% If all nodes go down, exit(allnodescrashed) is evaluated. -% -% Any of the above may be used as a malt, or may be combined into a list. -% {nodes, NodeList} and {processes, X} may not be combined. -% -% === Examples === -% % start a process for each element (1-element sublists)
-% 1 -% -% % start a process for each ten elements (10-element sublists)
-% 10 -% -% % split the list into two sublists and process in two processes
-% {processes, 2} -% -% % split the list into X sublists and process in X processes,
-% % where X is the number of cores in the machine
-% {processes, schedulers} -% -% % split the list into 10-element sublists and process in two processes
-% [10, {processes, 2}] -% -% % timeout after one second. Assumes that a process should be started
-% % for each element.
-% {timeout, 1000} -% -% % Runs 3 processes at a time on apple@desktop, -% and 2 on orange@laptop
-% % This is the best way to utilize all the CPU-power of a dual-core
-% % desktop and a single-core laptop. Assumes that the list should be
-% % split into 1-element sublists.
-% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} -% -% Like above, but makes plists figure out how many processes to use. -% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} -% -% % Gives apple and orange three seconds to process the list as
-% % 100-element sublists.
-% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] -% -% === Aside: Why Malt? === -% I needed a word for this concept, so maybe my subconsciousness gave me one by -% making me misspell multiply. Maybe it is an acronym for Malt is A List -% Tearing Specification. Maybe it is a beer metaphor, suggesting that code -% only runs in parallel if bribed with spirits. It's jargon, learn it -% or you can't be part of the in-group. -% -% == Messages and Errors == -% plists assures that no extraneous messages are left in or will later -% enter the message queue. This is guaranteed even in the event of an error. -% -% Errors in spawned processes are caught and propagated to the calling -% process. If you invoke -% -% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). -% -% you get a badarith error, exactly like when you use lists:map. -% -% plists uses monitors to watch the processes it spawns. It is not a good idea -% to invoke plists when you are already monitoring processes. If one of them -% does a non-normal exit, plists receives the 'DOWN' message believing it to be -% from one of its own processes. The error propagation system goes into -% effect, which results in the error occuring in the calling process. -% -% == License == -% The MIT License -% -% Copyright (c) 2007 Stephen Marsh -% -% Permission is hereby granted, free of charge, to any person obtaining a copy -% of this software and associated documentation files (the "Software"), to deal -% in the Software without restriction, including without limitation the rights -% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -% copies of the Software, and to permit persons to whom the Software is -% furnished to do so, subject to the following conditions: -% -% The above copyright notice and this permission notice shall be included in -% all copies or substantial portions of the Software. -% -% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -% THE SOFTWARE. - - --module(plists). --export([all/2, all/3, any/2, any/3, filter/2, filter/3, -fold/3, fold/4, fold/5, foreach/2, foreach/3, map/2, map/3, -partition/2, partition/3, sort/1, sort/2, sort/3, -usort/1, usort/2, usort/3, mapreduce/2, mapreduce/3, mapreduce/5, -runmany/3, runmany/4]). - -% Everything here is defined in terms of runmany. -% The following methods are convient interfaces to runmany. - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> bool() -all(Fun, List) -> - all(Fun, List, 1). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> bool() -all(Fun, List, Malt) -> - try runmany(fun (L) -> - B = lists:all(Fun, L), - if B -> - nil; - true -> - exit(notall) - end - end, - fun (_A1, _A2) -> - nil - end, - List, Malt) of - _ -> - true - catch exit:notall -> - false - end. - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> bool() -any(Fun, List) -> - any(Fun, List, 1). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> bool() -any(Fun, List, Malt) -> - try runmany(fun (L) -> - B = lists:any(Fun, L), - if B -> - exit(any); - true -> - nil - end - end, - fun (_A1, _A2) -> - nil - end, - List, Malt) of - _ -> - false - catch exit:any -> - true - end. - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() -filter(Fun, List) -> - filter(Fun, List, 1). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> list() -filter(Fun, List, Malt) -> - runmany(fun (L) -> - lists:filter(Fun, L) - end, - {reverse, fun (A1, A2) -> - A1 ++ A2 - end}, - List, Malt). - -% Note that with parallel fold there is not foldl and foldr, -% instead just one fold that can fuse Accumlators. - -% @doc Like below, but assumes 1 as the Malt. This function is almost useless, -% and is intended only to aid converting code from using lists to plists. -% @spec (Fun, InitAcc, List) -> term() -fold(Fun, InitAcc, List) -> - fold(Fun, Fun, InitAcc, List, 1). - -% @doc Like below, but uses the Fun as the Fuse by default. -% @spec (Fun, InitAcc, List, Malt) -> term() -fold(Fun, InitAcc, List, Malt) -> - fold(Fun, Fun, InitAcc, List, Malt). - -% @doc fold is more complex when made parallel. There is no foldl and foldr, -% accumulators aren't passed in any defined order. -% The list is split into sublists which are folded together. Fun is -% identical to the function passed to lists:fold[lr], it takes -% (an element, and the accumulator) and returns -> a new accumulator. -% It is used for the initial stage of folding sublists. Fuse fuses together -% the results, it takes (Results1, Result2) and returns -> a new result. -% By default sublists are fused left to right, each result of a fuse being -% fed into the first element of the next fuse. The result of the last fuse -% is the result. -% -% Fusing may also run in parallel using a recursive algorithm, -% by specifying the fuse as {recursive, Fuse}. See -% the discussion in {@link runmany/4}. -% -% Malt is the malt for the initial folding of sublists, and for the -% possible recursive fuse. -% @spec (Fun, Fuse, InitAcc, List, Malt) -> term() -fold(Fun, Fuse, InitAcc, List, Malt) -> - Fun2 = fun (L) -> lists:foldl(Fun, InitAcc, L) end, - runmany(Fun2, Fuse, List, Malt). - -% @doc Similiar to foreach in module -% lists -% except it makes no guarantee about the order it processes list elements. -% @spec (Fun, List) -> void() -foreach(Fun, List) -> - foreach(Fun, List, 1). - -% @doc Similiar to foreach in module -% lists -% except it makes no guarantee about the order it processes list elements. -% @spec (Fun, List, Malt) -> void() -foreach(Fun, List, Malt) -> - runmany(fun (L) -> - lists:foreach(Fun, L) - end, - fun (_A1, _A2) -> - ok - end, - List, Malt). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() -map(Fun, List) -> - map(Fun, List, 1). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> list() -map(Fun, List, Malt) -> - runmany(fun (L) -> - lists:map(Fun, L) - end, - {reverse, fun (A1, A2) -> - A1 ++ A2 - end}, - List, Malt). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> {list(), list()} -partition(Fun, List) -> - partition(Fun, List, 1). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> {list(), list()} -partition(Fun, List, Malt) -> - runmany(fun (L) -> - lists:partition(Fun, L) - end, - {reverse, fun ({True1, False1}, {True2, False2}) -> - {True1 ++ True2, False1 ++ False2} - end}, - List, Malt). - -% SORTMALT needs to be tuned --define(SORTMALT, 100). - -% @doc Same semantics as in module -% lists. -% @spec (List) -> list() -sort(List) -> - sort(fun (A, B) -> - A =< B - end, - List). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() -sort(Fun, List) -> - sort(Fun, List, ?SORTMALT). - -% @doc This version lets you specify your own malt for sort. -% -% sort splits the list into sublists and sorts them, and it merges the -% sorted lists together. These are done in parallel. Each sublist is -% sorted in a seperate process, and each merging of results is done in a -% seperate process. Malt defaults to 100, causing the list to be split into -% 100-element sublists. -% @spec (Fun, List, Malt) -> list() -sort(Fun, List, Malt) -> - Fun2 = fun (L) -> - lists:sort(Fun, L) - end, - Fuse = fun (A1, A2) -> - lists:merge(Fun, A1, A2) - end, - runmany(Fun2, {recursive, Fuse}, List, Malt). - -% @doc Same semantics as in module -% lists. -% @spec (List) -> list() -usort(List) -> - usort(fun (A, B) -> - A =< B - end, - List). - -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() -usort(Fun, List) -> - usort(Fun, List, ?SORTMALT). - -% @doc This version lets you specify your own malt for usort. -% -% usort splits the list into sublists and sorts them, and it merges the -% sorted lists together. These are done in parallel. Each sublist is -% sorted in a seperate process, and each merging of results is done in a -% seperate process. Malt defaults to 100, causing the list to be split into -% 100-element sublists. -% -% usort removes duplicate elments while it sorts. -% @spec (Fun, List, Malt) -> list() -usort(Fun, List, Malt) -> - Fun2 = fun (L) -> - lists:usort(Fun, L) - end, - Fuse = fun (A1, A2) -> - lists:umerge(Fun, A1, A2) - end, - runmany(Fun2, {recursive, Fuse}, List, Malt). - -% @doc Like below, assumes default MapMalt of 1. -% @spec (MapFunc, List) -> Dict -% MapFunc = (term()) -> DeepListOfKeyValuePairs -% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} -mapreduce(MapFunc, List) -> - mapreduce(MapFunc, List, 1). - -% Like below, but uses a default reducer that collects all -% {Key, Value} pairs into a -% dict, -% with values {Key, [Value1, Value2...]}. -% This dict is returned as the result. -mapreduce(MapFunc, List, MapMalt) -> - mapreduce(MapFunc, List, dict:new(), fun add_key/3, MapMalt). - -% @doc This is a very basic mapreduce. You won't write a Google-rivaling -% search engine with it. It has no equivalent in lists. Each -% element in the list is run through the MapFunc, which produces either -% a {Key, Value} pair, or a lists of key value pairs, or a list of lists of -% key value pairs...etc. A reducer process runs in parallel with the mapping -% processes, collecting the key value pairs. It starts with a state given by -% InitState, and for each {Key, Value} pair that it receives it invokes -% ReduceFunc(OldState, Key, Value) to compute its new state. mapreduce returns -% the reducer's final state. -% -% MapMalt is the malt for the mapping operation, with a default value of 1, -% meaning each element of the list is mapped by a seperate process. -% -% mapreduce requires OTP R11B, or it may leave monitoring messages in the -% message queue. -% @spec (MapFunc, List, InitState, ReduceFunc, MapMalt) -> Dict -% MapFunc = (term()) -> DeepListOfKeyValuePairs -% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} -% ReduceFunc = (OldState::term(), Key::term(), Value::term() -> NewState::term() -mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> - Parent = self(), - {Reducer, ReducerRef} = - erlang:spawn_monitor(fun () -> - reducer(Parent, 0, InitState, ReduceFunc) - end), - MapFunc2 = fun (L) -> - Reducer ! lists:map(MapFunc, L), - 1 - end, - SentMessages = try runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) - catch - exit:Reason -> - erlang:demonitor(ReducerRef, [flush]), - Reducer ! die, - exit(Reason) - end, - Reducer ! {mappers, done, SentMessages}, - Results = receive - {Reducer, Results2} -> - Results2; - {'DOWN', _, _, Reducer, Reason2} -> - exit(Reason2) - end, - receive - {'DOWN', _, _, Reducer, normal} -> - nil - end, - Results. - -reducer(Parent, NumReceived, State, Func) -> - receive - die -> - nil; - {mappers, done, NumReceived} -> - Parent ! {self (), State}; - Keys -> - reducer(Parent, NumReceived + 1, each_key(State, Func, Keys), Func) - end. - -each_key(State, Func, {Key, Value}) -> - Func(State, Key, Value); -each_key(State, Func, [List|Keys]) -> - each_key(each_key(State, Func, List), Func, Keys); -each_key(State, _, []) -> - State. - -add_key(Dict, Key, Value) -> - case dict:is_key(Key, Dict) of - true -> - dict:append(Key, Value, Dict); - false -> - dict:store(Key, [Value], Dict) - end. - -% @doc Like below, but assumes a Malt of 1, -% meaning each element of the list is processed by a seperate process. -% @spec (Fun, Fuse, List) -> term() -runmany(Fun, Fuse, List) -> - runmany(Fun, Fuse, List, 1). - -% Begin internal stuff (though runmany/4 is exported). - -% @doc All of the other functions are implemented with runmany. runmany -% takes a List, splits it into sublists, and starts processes to operate on -% each sublist, all done according to Malt. Each process passes its sublist -% into Fun and sends the result back. -% -% The results are then fused together to get the final result. There are two -% ways this can operate, lineraly and recursively. If Fuse is a function, -% a fuse is done linearly left-to-right on the sublists, the results -% of processing the first and second sublists being passed to Fuse, then -% the result of the first fuse and processing the third sublits, and so on. If -% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results -% of processing the second-to-last and last sublists being passed to FuseFunc, -% then the results of processing the third-to-last sublist and -% the results of the first fuse, and and so forth. -% Both methods preserve the original order of the lists elements. -% -% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. -% The recursive fuse makes no guarantee about the order the results of -% sublists, or the results of fuses are passed to FuseFunc. It -% continues fusing pairs of results until it is down to one. -% -% Recursive fuse is down in parallel with processing the sublists, and a -% process is spawned to fuse each pair of results. It is a parallized -% algorithm. Linear fuse is done after all results of processing sublists -% have been collected, and can only run in a single process. -% -% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if -% the malt contains {nodes, NodeList} or {processes, X}. If this is not the -% case, a linear fuse is done. -% @spec (Fun, Fuse, List, Malt) -> term() -% Fun = (list()) -> term() -% Fuse = FuseFunc | {recursive, FuseFunc} -% FuseFunc = (term(), term()) -> term() -runmany(Fun, Fuse, List, Malt) when is_list(Malt) -> - runmany(Fun, Fuse, List, local, no_split, Malt); -runmany(Fun, Fuse, List, Malt) -> - runmany(Fun, Fuse, List, [Malt]). - -runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) when is_integer(MaltTerm) -> - runmany(Fun, Fuse, List, Nodes, MaltTerm, Malt); -% run a process for each scheduler -runmany(Fun, Fuse, List, local, Split, [{processes, schedulers}|Malt]) -> - S = erlang:system_info(schedulers), - runmany(Fun, Fuse, List, local, Split, [{processes, S}|Malt]); -% Split the list into X sublists, where X is the number of processes -runmany(Fun, Fuse, List, local, no_split, [{processes, X}|_]=Malt) -> - L = length(List), - case L rem X of - 0 -> - runmany(Fun, Fuse, List, local, L div X, Malt); - _ -> - runmany(Fun, Fuse, List, local, L div X + 1, Malt) - end; -% run X process on local machine -runmany(Fun, Fuse, List, local, Split, [{processes, X}|Malt]) -> - Nodes = lists:duplicate(X, node()), - runmany(Fun, Fuse, List, Nodes, Split, Malt); -runmany(Fun, Fuse, List, Nodes, Split, [{timeout, X}|Malt]) -> - Parent = self(), - Timer = spawn(fun () -> - receive - stoptimer -> - Parent ! {timerstopped, self()} - after X -> - Parent ! {timerrang, self()}, - receive - stoptimer -> - Parent ! {timerstopped, self()} - end - end - end), - Ans = try runmany(Fun, Fuse, List, Nodes, Split, Malt) - catch - % we really just want the after block, the syntax - % makes this catch necessary. - willneverhappen -> - nil - after - Timer ! stoptimer, - cleanup_timer(Timer) - end, - Ans; -runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> - Nodes = lists:foldl(fun ({Node, schedulers}, A) -> - X = schedulers_on_node(Node) + 1, - lists:reverse(lists:duplicate(X, Node), A); - ({Node, X}, A) -> - lists:reverse(lists:duplicate(X, Node), A); - (Node, A) -> - [Node|A] - end, - [], NodeList), - runmany(Fun, Fuse, List, Nodes, Split, Malt); -% local recursive fuse, for when we weren't invoked with {processes, X} -% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. -runmany(Fun, {recursive, Fuse}, List, local, Split, []) -> - runmany(Fun, Fuse, List, local, Split, []); -% by default, operate on each element seperately -runmany(Fun, Fuse, List, Nodes, no_split, []) -> - runmany(Fun, Fuse, List, Nodes, 1, []); -runmany(Fun, Fuse, List, local, Split, []) -> - List2 = splitmany(List, Split), - local_runmany(Fun, Fuse, List2); -runmany(Fun, Fuse, List, Nodes, Split, []) -> - List2 = splitmany(List, Split), - cluster_runmany(Fun, Fuse, List2, Nodes). - -cleanup_timer(Timer) -> - receive - {timerrang, Timer} -> - cleanup_timer(Timer); - {timerstopped, Timer} -> - nil - end. - -schedulers_on_node(Node) -> - case get(plists_schedulers_on_nodes) of - undefined -> - X = determine_schedulers(Node), - put(plists_schedulers_on_nodes, - dict:store(Node, X, dict:new())), - X; - Dict -> - case dict:is_key(Node, Dict) of - true -> - dict:fetch(Node, Dict); - false -> - X = determine_schedulers(Node), - put(plists_schedulers_on_nodes, - dict:store(Node, X, Dict)), - X - end - end. - -determine_schedulers(Node) -> - Parent = self(), - Child = spawn(Node, fun () -> - Parent ! {self(), erlang:system_info(schedulers)} - end), - erlang:monitor(process, Child), - receive - {Child, X} -> - receive - {'DOWN', _, _, Child, _Reason} -> - nil - end, - X; - {'DOWN', _, _, Child, Reason} when Reason =/= normal -> - 0 - end. - -% local runmany, for when we weren't invoked with {processes, X} -% or {nodes, NodeList}. Every sublist is processed in parallel. -local_runmany(Fun, Fuse, List) -> - Parent = self (), - Pids = lists:map(fun (L) -> - F = fun () -> - Parent ! - {self (), Fun(L)} - end, - {Pid, _} = erlang:spawn_monitor(F), - Pid - end, - List), - Answers = try lists:map(fun receivefrom/1, Pids) - catch throw:Message -> - {BadPid, Reason} = Message, - handle_error(BadPid, Reason, Pids) - end, - lists:foreach(fun (Pid) -> - normal_cleanup(Pid) - end, Pids), - fuse(Fuse, Answers). - -receivefrom(Pid) -> - receive - {Pid, R} -> - R; - {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> - throw({BadPid, Reason}); - {timerrang, _} -> - throw({nil, timeout}) - end. - -% Convert List into [{Number, Sublist}] -cluster_runmany(Fun, Fuse, List, Nodes) -> - {List2, _} = lists:foldl(fun (X, {L, Count}) -> - {[{Count, X}|L], Count+1} - end, - {[], 0}, List), - cluster_runmany(Fun, Fuse, List2, Nodes, [], []). - -% Add a pair of results into the TaskList as a fusing task -cluster_runmany(Fun, {recursive, Fuse}, [], Nodes, Running, - [{_, R1}, {_, R2}|Results]) -> - cluster_runmany(Fun, {recursive, Fuse}, [{fuse, R1, R2}], Nodes, - Running, Results); -% recursive fuse done, return result -cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], [{_, Result}]) -> - Result; -% edge case where we are asked to do nothing -cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], []) -> - []; -% We're done, now we just have to [linear] fuse the results -cluster_runmany(_, Fuse, [], _Nodes, [], Results) -> - fuse(Fuse, lists:map(fun ({_, R}) -> R end, - lists:sort(fun ({A, _}, {B, _}) -> - A =< B - end, - lists:reverse(Results)))); -% We have a ready node and a sublist or fuse to be processed, so we start -% a new process -cluster_runmany(Fun, Fuse, [Task|TaskList], [N|Nodes], Running, Results) -> - Parent = self(), - case Task of - {Num, L2} -> - Fun2 = fun () -> - Parent ! {self(), Num, Fun(L2)} - end; - {fuse, R1, R2} -> - {recursive, FuseFunc} = Fuse, - Fun2 = fun () -> - Parent ! {self(), fuse, FuseFunc(R1, R2)} - end - end, - Fun3 = fun () -> - try Fun2() - catch - exit:siblingdied -> - ok; - exit:Reason -> - Parent ! {self(), error, Reason}; - error:R -> - Parent ! {self(), error, {R, erlang:get_stacktrace()}}; - throw:R -> - Parent ! {self(), error, {{nocatch, R}, erlang:get_stacktrace()}} - end - end, - Pid = spawn(N, Fun3), - erlang:monitor(process, Pid), - cluster_runmany(Fun, Fuse, TaskList, Nodes, [{Pid, N, Task}|Running], Results); -% We can't start a new process, but can watch over already running ones -cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Running) > 0 -> - receive - {_Pid, error, Reason} -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(junkvalue, Reason, RunningPids); - {Pid, Num, Result} -> - % throw out the exit message, Reason should be - % normal, noproc, or noconnection - receive {'DOWN', _, _, Pid, _Reason} -> - nil - end, - {Running2, FinishedNode, _} = delete_running(Pid, Running, []), - cluster_runmany(Fun, Fuse, TaskList, - [FinishedNode|Nodes], Running2, [{Num, Result}|Results]); - {timerrang, _} -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(nil, timeout, RunningPids); - % node failure - {'DOWN', _, _, Pid, noconnection} -> - {Running2, _DeadNode, Task} = delete_running(Pid, Running, []), - cluster_runmany(Fun, Fuse, [Task|TaskList], Nodes, - Running2, Results); - % could a noproc exit message come before the message from - % the process? we are assuming it can't. - % this clause is unlikely to get invoked due to cluster_runmany's - % spawned processes. It will still catch errors in mapreduce's - % reduce process, however. - {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(BadPid, Reason, RunningPids) - end; -% We have data, but no nodes either available or occupied -cluster_runmany(_, _, [_Non|_Empty], []=_Nodes, []=_Running, _) -> - exit(allnodescrashed). - -delete_running(Pid, [{Pid, Node, List}|Running], Acc) -> - {Running ++ Acc, Node, List}; -delete_running(Pid, [R|Running], Acc) -> - delete_running(Pid, Running, [R|Acc]). - -handle_error(BadPid, Reason, Pids) -> - lists:foreach(fun (Pid) -> - exit(Pid, siblingdied) - end, Pids), - lists:foreach(fun (Pid) -> - error_cleanup(Pid, BadPid) - end, Pids), - exit(Reason). - -error_cleanup(BadPid, BadPid) -> - ok; -error_cleanup(Pid, BadPid) -> - receive - {Pid, _} -> - error_cleanup(Pid, BadPid); - {Pid, _, _} -> - error_cleanup(Pid, BadPid); - {'DOWN', _, _, Pid, _Reason} -> - ok - end. - -normal_cleanup(Pid) -> - receive - {'DOWN', _, _, Pid, _Reason} -> - ok - end. - -% edge case -fuse(_, []) -> - []; -fuse({reverse, _}=Fuse, Results) -> - [RL|ResultsR] = lists:reverse(Results), - fuse(Fuse, ResultsR, RL); -fuse(Fuse, [R1|Results]) -> - fuse(Fuse, Results, R1). - -fuse({reverse, FuseFunc}=Fuse, [R2|Results], R1) -> - fuse(Fuse, Results, FuseFunc(R2, R1)); -fuse(Fuse, [R2|Results], R1) -> - fuse(Fuse, Results, Fuse(R1, R2)); -fuse(_, [], R) -> - R. - -% Splits a list into a list of sublists, each of size Size, -% except for the last element which is less if the original list -% could not be evenly divided into Size-sized lists. -splitmany(List, Size) -> - splitmany(List, [], Size). - -splitmany([], Acc, _) -> - lists:reverse(Acc); -splitmany(List, Acc, Size) -> - {Top, NList} = split(Size, List), - splitmany(NList, [Top|Acc], Size). - -% Like lists:split, except it splits a list smaller than its first -% parameter -split(Size, List) -> - split(Size, List, []). - -split(0, List, Acc) -> - {lists:reverse(Acc), List}; -split(Size, [H|List], Acc) -> - split(Size - 1, List, [H|Acc]); -split(_, [], Acc) -> - {lists:reverse(Acc), []}. From c7717743ed72677f95fc8df4eec0b11650a04041 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 15:41:28 -0500 Subject: [PATCH 052/240] bring ec_plists up to erlware standards Signed-off-by: Jordan Wilberding --- src/ec_plists.erl | 962 +++++++++++++++++++++------------------ test/ec_plists_tests.erl | 75 +++ 2 files changed, 598 insertions(+), 439 deletions(-) create mode 100644 test/ec_plists_tests.erl diff --git a/src/ec_plists.erl b/src/ec_plists.erl index 688d5a5..a021d02 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -1,214 +1,264 @@ -% @author Stephen Marsh -% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] -% @doc plists is a drop-in replacement for module -% lists, -% making most list operations parallel. It can operate on each element in -% parallel, for IO-bound operations, on sublists in parallel, for -% taking advantage of multi-core machines with CPU-bound operations, and -% across erlang nodes, for parallizing inside a cluster. It handles -% errors and node failures. It can be configured, tuned, and tweaked to -% get optimal performance while minimizing overhead. -% -% Almost all the functions are -% identical to equivalent functions in lists, returning exactly the same -% result, and having both a form with an identical syntax that operates on -% each element in parallel and a form which takes an optional "malt", -% a specification for how to parallize the operation. -% -% fold is the one exception, parallel fold is different from linear fold. -% This module also include a simple mapreduce implementation, and the -% function runmany. All the other functions are implemented with runmany, -% which is as a generalization of parallel list operations. -% -% == Malts == -% A malt specifies how to break a list into sublists, and can optionally -% specify a timeout, which nodes to run on, and how many processes to start -% per node. -% -% Malt = MaltComponent | [MaltComponent]
-% MaltComponent = SubListSize::integer() | {processes, integer()} | -% {processes, schedulers} | -% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
-% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | -% {Node::atom(), schedulers} -% -% An integer can be given to specify the exact size for -% sublists. 1 is a good choice for IO-bound operations and when -% the operation on each list element is expensive. Larger numbers -% minimize overhead and are faster for cheap operations. -% -% If the integer is omitted, and -% you have specified a {processes, X}, the list is -% split into X sublists. This is only -% useful when the time to process each element is close to identical and you -% know exactly how many lines of execution are available to you. -% -% If neither of the above applies, the sublist size defaults to 1. -% -% You can use {processes, X} to have the list processed -% by X processes on the local machine. A good choice for X is the number of -% lines of execution (cores) the machine provides. This can be done -% automatically with {processes, schedulers}, which sets -% the number of processes to the number of schedulers in the erlang virtual -% machine (probably equal to the number of cores). -% -% {timeout, Milliseconds} specifies a timeout. This is a timeout for the entire -% operation, both operating on the sublists and combining the results. -% exit(timeout) is evaluated if the timeout is exceeded. -% -% {nodes, NodeList} specifies that the operation should be done across nodes. -% Every element of NodeList is of the form {NodeName, NumProcesses} or -% NodeName, which means the same as {NodeName, 1}. plists runs -% NumProcesses processes on NodeName concurrently. A good choice for -% NumProcesses is the number of lines of execution (cores) a node provides -% plus one. This ensures the node is completely busy even when -% fetching a new sublist. This can be done automatically with -% {NodeName, schedulers}, in which case -% plists uses a cached value if it has one, and otherwise finds the number of -% schedulers in the remote node and adds one. This will ensure at least one -% busy process per core (assuming the node has a scheduler for each core). -% -% plists is able to recover if a node goes down. -% If all nodes go down, exit(allnodescrashed) is evaluated. -% -% Any of the above may be used as a malt, or may be combined into a list. -% {nodes, NodeList} and {processes, X} may not be combined. -% -% === Examples === -% % start a process for each element (1-element sublists)
-% 1 -% -% % start a process for each ten elements (10-element sublists)
-% 10 -% -% % split the list into two sublists and process in two processes
-% {processes, 2} -% -% % split the list into X sublists and process in X processes,
-% % where X is the number of cores in the machine
-% {processes, schedulers} -% -% % split the list into 10-element sublists and process in two processes
-% [10, {processes, 2}] -% -% % timeout after one second. Assumes that a process should be started
-% % for each element.
-% {timeout, 1000} -% -% % Runs 3 processes at a time on apple@desktop, -% and 2 on orange@laptop
-% % This is the best way to utilize all the CPU-power of a dual-core
-% % desktop and a single-core laptop. Assumes that the list should be
-% % split into 1-element sublists.
-% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} -% -% Like above, but makes plists figure out how many processes to use. -% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} -% -% % Gives apple and orange three seconds to process the list as
-% % 100-element sublists.
-% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] -% -% === Aside: Why Malt? === -% I needed a word for this concept, so maybe my subconsciousness gave me one by -% making me misspell multiply. Maybe it is an acronym for Malt is A List -% Tearing Specification. Maybe it is a beer metaphor, suggesting that code -% only runs in parallel if bribed with spirits. It's jargon, learn it -% or you can't be part of the in-group. -% -% == Messages and Errors == -% plists assures that no extraneous messages are left in or will later -% enter the message queue. This is guaranteed even in the event of an error. -% -% Errors in spawned processes are caught and propagated to the calling -% process. If you invoke -% -% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). -% -% you get a badarith error, exactly like when you use lists:map. -% -% plists uses monitors to watch the processes it spawns. It is not a good idea -% to invoke plists when you are already monitoring processes. If one of them -% does a non-normal exit, plists receives the 'DOWN' message believing it to be -% from one of its own processes. The error propagation system goes into -% effect, which results in the error occuring in the calling process. -% -% == License == -% The MIT License -% -% Copyright (c) 2007 Stephen Marsh -% -% Permission is hereby granted, free of charge, to any person obtaining a copy -% of this software and associated documentation files (the "Software"), to deal -% in the Software without restriction, including without limitation the rights -% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -% copies of the Software, and to permit persons to whom the Software is -% furnished to do so, subject to the following conditions: -% -% The above copyright notice and this permission notice shall be included in -% all copies or substantial portions of the Software. -% -% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -% THE SOFTWARE. +%%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%%% The MIT License +%%% +%%% Copyright (c) 2007 Stephen Marsh +%%% +%%% Permission is hereby granted, free of charge, to any person obtaining a copy +%%% of this software and associated documentation files (the "Software"), to deal +%%% in the Software without restriction, including without limitation the rights +%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +%%% copies of the Software, and to permit persons to whom the Software is +%%% furnished to do so, subject to the following conditions: +%%% +%%% The above copyright notice and this permission notice shall be included in +%%% all copies or substantial portions of the Software. +%%% +%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +%%% THE SOFTWARE. +%%%--------------------------------------------------------------------------- +%%% @author Stephen Marsh +%%% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] +%%% @doc +%%% plists is a drop-in replacement for module lists, making +%%% most list operations parallel. It can operate on each element in +%%% parallel, for IO-bound operations, on sublists in parallel, for +%%% taking advantage of multi-core machines with CPU-bound operations, +%%% and across erlang nodes, for parallizing inside a cluster. It +%%% handles errors and node failures. It can be configured, tuned, and +%%% tweaked to get optimal performance while minimizing overhead. +%%% +%%% Almost all the functions are identical to equivalent functions in +%%% lists, returning exactly the same result, and having both a form +%%% with an identical syntax that operates on each element in parallel +%%% and a form which takes an optional "malt", a specification for how +%%% to parallize the operation. +%%% +%%% fold is the one exception, parallel fold is different from linear +%%% fold. This module also include a simple mapreduce implementation, +%%% and the function runmany. All the other functions are implemented +%%% with runmany, which is as a generalization of parallel list +%%% operations. +%%% +%%% Malts +%%% ===== +%%% +%%% A malt specifies how to break a list into sublists, and can optionally +%%% specify a timeout, which nodes to run on, and how many processes to start +%%% per node. +%%% +%%% Malt = MaltComponent | [MaltComponent] +%%% MaltComponent = SubListSize::integer() | {processes, integer()} | +%%% {processes, schedulers} | +%%% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
+%%% +%%% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | +%%% {Node::atom(), schedulers} +%%% +%%% An integer can be given to specify the exact size for sublists. 1 +%%% is a good choice for IO-bound operations and when the operation on +%%% each list element is expensive. Larger numbers minimize overhead +%%% and are faster for cheap operations. +%%% +%%% If the integer is omitted, and you have specified a `{processes, +%%% X}`, the list is split into X sublists. This is only useful when +%%% the time to process each element is close to identical and you +%%% know exactly how many lines of execution are available to you. +%%% +%%% If neither of the above applies, the sublist size defaults to 1. +%%% +%%% You can use `{processes, X}` to have the list processed by `X` +%%% processes on the local machine. A good choice for `X` is the +%%% number of lines of execution (cores) the machine provides. This +%%% can be done automatically with {processes, schedulers}, which sets +%%% the number of processes to the number of schedulers in the erlang +%%% virtual machine (probably equal to the number of cores). +%%% +%%% `{timeout, Milliseconds}` specifies a timeout. This is a timeout +%%% for the entire operation, both operating on the sublists and +%%% combining the results. exit(timeout) is evaluated if the timeout +%%% is exceeded. +%%% +%%% `{nodes, NodeList}` specifies that the operation should be done +%%% across nodes. Every element of NodeList is of the form +%%% `{NodeName, NumProcesses}` or NodeName, which means the same as +%%% `{NodeName, 1}`. plists runs NumProcesses processes on NodeName +%%% concurrently. A good choice for NumProcesses is the number of +%%% lines of execution (cores) a node provides plus one. This ensures +%%% the node is completely busy even when fetching a new sublist. This +%%% can be done automatically with `{NodeName, schedulers}`, in which +%%% case plists uses a cached value if it has one, and otherwise finds +%%% the number of schedulers in the remote node and adds one. This +%%% will ensure at least one busy process per core (assuming the node +%%% has a scheduler for each core). +%%% +%%% plists is able to recover if a node goes down. If all nodes go +%%% down, exit(allnodescrashed) is evaluated. +%%% +%%% Any of the above may be used as a malt, or may be combined into a +%%% list. `{nodes, NodeList}` and {processes, X} may not be combined. +%%% +%%% Examples +%%% ======== +%%% +%%% %%start a process for each element (1-element sublists)< +%%% 1 +%%% +%%% %% start a process for each ten elements (10-element sublists) +%%% 10 +%%% +%%% %% split the list into two sublists and process in two processes +%%% {processes, 2} +%%% +%%% %% split the list into X sublists and process in X processes, +%%% %% where X is the number of cores in the machine +%%% {processes, schedulers} +%%% +%%% %% split the list into 10-element sublists and process in two processes +%%% [10, {processes, 2}] +%%% +%%% %% timeout after one second. Assumes that a process should be started +%%% %% for each element.
+%%% {timeout, 1000} +%%% +%%% %% Runs 3 processes at a time on apple@desktop, and 2 on orange@laptop +%%% %% This is the best way to utilize all the CPU-power of a dual-core
+%%% %% desktop and a single-core laptop. Assumes that the list should be
+%%% %% split into 1-element sublists.
+%%% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} +%%% +%%% %% Like above, but makes plists figure out how many processes to use. +%%% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} +%%% +%%% %% Gives apple and orange three seconds to process the list as
+%%% %% 100-element sublists.
+%%% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] +%%% +%%% Aside: Why Malt? +%%% ================ +%%% +%%% I needed a word for this concept, so maybe my subconsciousness +%%% gave me one by making me misspell multiply. Maybe it is an acronym +%%% for Malt is A List Tearing Specification. Maybe it is a beer +%%% metaphor, suggesting that code only runs in parallel if bribed +%%% with spirits. It's jargon, learn it or you can't be part of the +%%% in-group. +%%% +%%% Messages and Errors +%%% =================== +%%% +%%% plists assures that no extraneous messages are left in or will +%%% later enter the message queue. This is guaranteed even in the +%%% event of an error. +%%% +%%% Errors in spawned processes are caught and propagated to the +%%% calling process. If you invoke +%%% +%%% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). +%%% +%%% you get a badarith error, exactly like when you use lists:map. +%%% +%%% plists uses monitors to watch the processes it spawns. It is not a +%%% good idea to invoke plists when you are already monitoring +%%% processes. If one of them does a non-normal exit, plists receives +%%% the 'DOWN' message believing it to be from one of its own +%%% processes. The error propagation system goes into effect, which +%%% results in the error occuring in the calling process. +%%% +-module(ec_plists). +-export([all/2, all/3, + any/2, any/3, + filter/2, filter/3, + fold/3, fold/4, fold/5, + foreach/2, foreach/3, + map/2, map/3, + ftmap/2, ftmap/3, + partition/2, partition/3, + sort/1, sort/2, sort/3, + usort/1, usort/2, usort/3, + mapreduce/2, mapreduce/3, mapreduce/5, + runmany/3, runmany/4]). --module(plists). --export([all/2, all/3, any/2, any/3, filter/2, filter/3, -fold/3, fold/4, fold/5, foreach/2, foreach/3, map/2, map/3, -partition/2, partition/3, sort/1, sort/2, sort/3, -usort/1, usort/2, usort/3, mapreduce/2, mapreduce/3, mapreduce/5, -runmany/3, runmany/4]). +-export_type([malt/0, malt_component/0, node_spec/0, fuse/0, fuse_fun/0]). -% Everything here is defined in terms of runmany. -% The following methods are convient interfaces to runmany. +%%============================================================================ +%% types +%%============================================================================ -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> bool() +-type malt() :: malt_component() | [malt_component()]. + +-type malt_component() :: SubListSize::integer() + | {processes, integer()} + | {processes, schedulers} + | {timeout, Milliseconds::integer()} + | {nodes, [node_spec()]}. + +-type node_spec() :: Node::atom() + | {Node::atom(), NumProcesses::integer()} + | {Node::atom(), schedulers}. + +-type fuse_fun() :: fun((term(), term()) -> term()). +-type fuse() :: fuse_fun() | {recursive, fuse_fun()} | {reverse, fuse_fun()}. +-type el_fun() :: fun((term()) -> term()). + +%%============================================================================ +%% API +%%============================================================================ + +%% Everything here is defined in terms of runmany. +%% The following methods are convient interfaces to runmany. + +%% @doc Same semantics as in module +%% lists. +-spec all/2 :: (el_fun(), list()) -> boolean(). all(Fun, List) -> all(Fun, List, 1). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> bool() +%% @doc Same semantics as in module +%% lists. +-spec all/3 :: (el_fun(), list(), malt()) -> boolean(). all(Fun, List, Malt) -> - try runmany(fun (L) -> + try + runmany(fun (L) -> B = lists:all(Fun, L), - if B -> + if + B -> nil; - true -> - exit(notall) + true -> + erlang:throw(notall) end end, fun (_A1, _A2) -> nil end, - List, Malt) of - _ -> - true - catch exit:notall -> - false + List, Malt), + true + catch + throw:notall -> + false end. -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> bool() +%% @doc Same semantics as in module +%% lists. +-spec any/2 :: (fun(), list()) -> boolean(). any(Fun, List) -> any(Fun, List, 1). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> bool() +%% @doc Same semantics as in module +%% lists. +-spec any/3 :: (fun(), list(), malt()) -> boolean(). any(Fun, List, Malt) -> - try runmany(fun (L) -> + try + runmany(fun (L) -> B = lists:any(Fun, L), if B -> - exit(any); + erlang:throw(any); true -> nil end @@ -219,19 +269,19 @@ any(Fun, List, Malt) -> List, Malt) of _ -> false - catch exit:any -> + catch throw:any -> true end. -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec filter/2 :: (fun(), list()) -> list(). filter(Fun, List) -> filter(Fun, List, 1). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> list() +%% @doc Same semantics as in module +%% lists. +-spec filter/3 :: (fun(), list(), malt()) -> list(). filter(Fun, List, Malt) -> runmany(fun (L) -> lists:filter(Fun, L) @@ -241,53 +291,55 @@ filter(Fun, List, Malt) -> end}, List, Malt). -% Note that with parallel fold there is not foldl and foldr, -% instead just one fold that can fuse Accumlators. +%% Note that with parallel fold there is not foldl and foldr, +%% instead just one fold that can fuse Accumlators. -% @doc Like below, but assumes 1 as the Malt. This function is almost useless, -% and is intended only to aid converting code from using lists to plists. -% @spec (Fun, InitAcc, List) -> term() +%% @doc Like below, but assumes 1 as the Malt. This function is almost useless, +%% and is intended only to aid converting code from using lists to plists. +-spec fold/3 :: (fun(), InitAcc::term(), list()) -> term(). fold(Fun, InitAcc, List) -> fold(Fun, Fun, InitAcc, List, 1). -% @doc Like below, but uses the Fun as the Fuse by default. -% @spec (Fun, InitAcc, List, Malt) -> term() +%% @doc Like below, but uses the Fun as the Fuse by default. +-spec fold/4 :: (fun(), InitAcc::term(), list(), malt()) -> term(). fold(Fun, InitAcc, List, Malt) -> fold(Fun, Fun, InitAcc, List, Malt). -% @doc fold is more complex when made parallel. There is no foldl and foldr, -% accumulators aren't passed in any defined order. -% The list is split into sublists which are folded together. Fun is -% identical to the function passed to lists:fold[lr], it takes -% (an element, and the accumulator) and returns -> a new accumulator. -% It is used for the initial stage of folding sublists. Fuse fuses together -% the results, it takes (Results1, Result2) and returns -> a new result. -% By default sublists are fused left to right, each result of a fuse being -% fed into the first element of the next fuse. The result of the last fuse -% is the result. -% -% Fusing may also run in parallel using a recursive algorithm, -% by specifying the fuse as {recursive, Fuse}. See -% the discussion in {@link runmany/4}. -% -% Malt is the malt for the initial folding of sublists, and for the -% possible recursive fuse. -% @spec (Fun, Fuse, InitAcc, List, Malt) -> term() +%% @doc fold is more complex when made parallel. There is no foldl and +%% foldr, accumulators aren't passed in any defined order. The list +%% is split into sublists which are folded together. Fun is identical +%% to the function passed to lists:fold[lr], it takes (an element, and +%% the accumulator) and returns -> a new accumulator. It is used for +%% the initial stage of folding sublists. Fuse fuses together the +%% results, it takes (Results1, Result2) and returns -> a new result. +%% By default sublists are fused left to right, each result of a fuse +%% being fed into the first element of the next fuse. The result of +%% the last fuse is the result. +%% +%% Fusing may also run in parallel using a recursive algorithm, +%% by specifying the fuse as {recursive, Fuse}. See +%% the discussion in {@link runmany/4}. +%% +%% Malt is the malt for the initial folding of sublists, and for the +%% possible recursive fuse. +-spec fold/5 :: (fun(), fuse(), InitAcc::term(), list(), malt()) -> term(). fold(Fun, Fuse, InitAcc, List, Malt) -> - Fun2 = fun (L) -> lists:foldl(Fun, InitAcc, L) end, + Fun2 = fun (L) -> + lists:foldl(Fun, InitAcc, L) + end, runmany(Fun2, Fuse, List, Malt). -% @doc Similiar to foreach in module -% lists -% except it makes no guarantee about the order it processes list elements. -% @spec (Fun, List) -> void() +%% @doc Similiar to foreach in module +%% lists +%% except it makes no guarantee about the order it processes list elements. +-spec foreach/2 :: (fun(), list()) -> ok. foreach(Fun, List) -> foreach(Fun, List, 1). -% @doc Similiar to foreach in module -% lists -% except it makes no guarantee about the order it processes list elements. -% @spec (Fun, List, Malt) -> void() +%% @doc Similiar to foreach in module +%% lists +%% except it makes no guarantee about the order it processes list elements. +-spec foreach/3 :: (fun(), list(), malt()) -> ok. foreach(Fun, List, Malt) -> runmany(fun (L) -> lists:foreach(Fun, L) @@ -297,33 +349,57 @@ foreach(Fun, List, Malt) -> end, List, Malt). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec map/2 :: (fun(), list()) -> list(). map(Fun, List) -> map(Fun, List, 1). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> list() +%% @doc Same semantics as in module +%% lists. +-spec map/3 :: (fun(), list(), malt()) -> list(). map(Fun, List, Malt) -> runmany(fun (L) -> lists:map(Fun, L) end, {reverse, fun (A1, A2) -> - A1 ++ A2 - end}, + A1 ++ A2 + end}, List, Malt). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> {list(), list()} +%% @doc values are returned as {value, term()}. +-spec ftmap/2 :: (fun(), list()) -> list(). +ftmap(Fun, List) -> + map(fun(L) -> + try + {value, Fun(L)} + catch + Class:Type -> + {error, {Class, Type}} + end + end, List). + +%% @doc values are returned as {value, term()}. +-spec ftmap/3 :: (fun(), list(), malt()) -> list(). +ftmap(Fun, List, Malt) -> + map(fun(L) -> + try + {value, Fun(L)} + catch + Class:Type -> + {error, {Class, Type}} + end + end, List, Malt). + +%% @doc Same semantics as in module +%% lists. +-spec partition/2 :: (fun(), list()) -> {list(), list()}. partition(Fun, List) -> partition(Fun, List, 1). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List, Malt) -> {list(), list()} +%% @doc Same semantics as in module +%% lists. +-spec partition/3 :: (fun(), list(), malt()) -> {list(), list()}. partition(Fun, List, Malt) -> runmany(fun (L) -> lists:partition(Fun, L) @@ -333,109 +409,110 @@ partition(Fun, List, Malt) -> end}, List, Malt). -% SORTMALT needs to be tuned +%% SORTMALT needs to be tuned -define(SORTMALT, 100). -% @doc Same semantics as in module -% lists. -% @spec (List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec sort/1 :: (list()) -> list(). sort(List) -> sort(fun (A, B) -> A =< B end, List). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec sort/2 :: (fun(), list()) -> list(). sort(Fun, List) -> sort(Fun, List, ?SORTMALT). -% @doc This version lets you specify your own malt for sort. -% -% sort splits the list into sublists and sorts them, and it merges the -% sorted lists together. These are done in parallel. Each sublist is -% sorted in a seperate process, and each merging of results is done in a -% seperate process. Malt defaults to 100, causing the list to be split into -% 100-element sublists. -% @spec (Fun, List, Malt) -> list() +%% @doc This version lets you specify your own malt for sort. +%% +%% sort splits the list into sublists and sorts them, and it merges the +%% sorted lists together. These are done in parallel. Each sublist is +%% sorted in a seperate process, and each merging of results is done in a +%% seperate process. Malt defaults to 100, causing the list to be split into +%% 100-element sublists. +-spec sort/3 :: (fun(), list(), malt()) -> list(). sort(Fun, List, Malt) -> Fun2 = fun (L) -> - lists:sort(Fun, L) - end, + lists:sort(Fun, L) + end, Fuse = fun (A1, A2) -> - lists:merge(Fun, A1, A2) - end, + lists:merge(Fun, A1, A2) + end, runmany(Fun2, {recursive, Fuse}, List, Malt). -% @doc Same semantics as in module -% lists. -% @spec (List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec usort/1 :: (list()) -> list(). usort(List) -> usort(fun (A, B) -> - A =< B - end, + A =< B + end, List). -% @doc Same semantics as in module -% lists. -% @spec (Fun, List) -> list() +%% @doc Same semantics as in module +%% lists. +-spec usort/2 :: (fun(), list()) -> list(). usort(Fun, List) -> usort(Fun, List, ?SORTMALT). -% @doc This version lets you specify your own malt for usort. -% -% usort splits the list into sublists and sorts them, and it merges the -% sorted lists together. These are done in parallel. Each sublist is -% sorted in a seperate process, and each merging of results is done in a -% seperate process. Malt defaults to 100, causing the list to be split into -% 100-element sublists. -% -% usort removes duplicate elments while it sorts. -% @spec (Fun, List, Malt) -> list() +%% @doc This version lets you specify your own malt for usort. +%% +%% usort splits the list into sublists and sorts them, and it merges the +%% sorted lists together. These are done in parallel. Each sublist is +%% sorted in a seperate process, and each merging of results is done in a +%% seperate process. Malt defaults to 100, causing the list to be split into +%% 100-element sublists. +%% +%% usort removes duplicate elments while it sorts. +-spec usort/3 :: (fun(), list(), malt()) -> list(). usort(Fun, List, Malt) -> Fun2 = fun (L) -> - lists:usort(Fun, L) - end, + lists:usort(Fun, L) + end, Fuse = fun (A1, A2) -> - lists:umerge(Fun, A1, A2) - end, + lists:umerge(Fun, A1, A2) + end, runmany(Fun2, {recursive, Fuse}, List, Malt). -% @doc Like below, assumes default MapMalt of 1. -% @spec (MapFunc, List) -> Dict -% MapFunc = (term()) -> DeepListOfKeyValuePairs -% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} +%% @doc Like below, assumes default MapMalt of 1. +-spec mapreduce/2 :: (MapFunc, list()) -> dict() when + MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), + DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}. mapreduce(MapFunc, List) -> mapreduce(MapFunc, List, 1). -% Like below, but uses a default reducer that collects all -% {Key, Value} pairs into a -% dict, -% with values {Key, [Value1, Value2...]}. -% This dict is returned as the result. +%% Like below, but uses a default reducer that collects all +%% {Key, Value} pairs into a +%% dict, +%% with values {Key, [Value1, Value2...]}. +%% This dict is returned as the result. mapreduce(MapFunc, List, MapMalt) -> mapreduce(MapFunc, List, dict:new(), fun add_key/3, MapMalt). -% @doc This is a very basic mapreduce. You won't write a Google-rivaling -% search engine with it. It has no equivalent in lists. Each -% element in the list is run through the MapFunc, which produces either -% a {Key, Value} pair, or a lists of key value pairs, or a list of lists of -% key value pairs...etc. A reducer process runs in parallel with the mapping -% processes, collecting the key value pairs. It starts with a state given by -% InitState, and for each {Key, Value} pair that it receives it invokes -% ReduceFunc(OldState, Key, Value) to compute its new state. mapreduce returns -% the reducer's final state. -% -% MapMalt is the malt for the mapping operation, with a default value of 1, -% meaning each element of the list is mapped by a seperate process. -% -% mapreduce requires OTP R11B, or it may leave monitoring messages in the -% message queue. -% @spec (MapFunc, List, InitState, ReduceFunc, MapMalt) -> Dict -% MapFunc = (term()) -> DeepListOfKeyValuePairs -% DeepListOfKeyValuePairs = [DeepListOfKeyValuePairs] | {Key, Value} -% ReduceFunc = (OldState::term(), Key::term(), Value::term() -> NewState::term() +%% @doc This is a very basic mapreduce. You won't write a +%% Google-rivaling search engine with it. It has no equivalent in +%% lists. Each element in the list is run through the MapFunc, which +%% produces either a {Key, Value} pair, or a lists of key value pairs, +%% or a list of lists of key value pairs...etc. A reducer process runs +%% in parallel with the mapping processes, collecting the key value +%% pairs. It starts with a state given by InitState, and for each +%% {Key, Value} pair that it receives it invokes ReduceFunc(OldState, +%% Key, Value) to compute its new state. mapreduce returns the +%% reducer's final state. +%% +%% MapMalt is the malt for the mapping operation, with a default value of 1, +%% meaning each element of the list is mapped by a seperate process. +%% +%% mapreduce requires OTP R11B, or it may leave monitoring messages in the +%% message queue. +-spec mapreduce/5 :: (MapFunc, list(), InitState::term(), ReduceFunc, malt()) -> dict() when + MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), + DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}, + ReduceFunc :: fun((OldState::term(), Key::term(), Value::term()) -> NewState::term()). mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> Parent = self(), {Reducer, ReducerRef} = @@ -446,7 +523,8 @@ mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> Reducer ! lists:map(MapFunc, L), 1 end, - SentMessages = try runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) + SentMessages = try + runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) catch exit:Reason -> erlang:demonitor(ReducerRef, [flush]), @@ -491,94 +569,94 @@ add_key(Dict, Key, Value) -> dict:store(Key, [Value], Dict) end. -% @doc Like below, but assumes a Malt of 1, -% meaning each element of the list is processed by a seperate process. -% @spec (Fun, Fuse, List) -> term() +%% @doc Like below, but assumes a Malt of 1, +%% meaning each element of the list is processed by a seperate process. +-spec runmany/3 :: (fun(), fuse(), list()) -> term(). runmany(Fun, Fuse, List) -> runmany(Fun, Fuse, List, 1). -% Begin internal stuff (though runmany/4 is exported). +%% Begin internal stuff (though runmany/4 is exported). -% @doc All of the other functions are implemented with runmany. runmany -% takes a List, splits it into sublists, and starts processes to operate on -% each sublist, all done according to Malt. Each process passes its sublist -% into Fun and sends the result back. -% -% The results are then fused together to get the final result. There are two -% ways this can operate, lineraly and recursively. If Fuse is a function, -% a fuse is done linearly left-to-right on the sublists, the results -% of processing the first and second sublists being passed to Fuse, then -% the result of the first fuse and processing the third sublits, and so on. If -% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results -% of processing the second-to-last and last sublists being passed to FuseFunc, -% then the results of processing the third-to-last sublist and -% the results of the first fuse, and and so forth. -% Both methods preserve the original order of the lists elements. -% -% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. -% The recursive fuse makes no guarantee about the order the results of -% sublists, or the results of fuses are passed to FuseFunc. It -% continues fusing pairs of results until it is down to one. -% -% Recursive fuse is down in parallel with processing the sublists, and a -% process is spawned to fuse each pair of results. It is a parallized -% algorithm. Linear fuse is done after all results of processing sublists -% have been collected, and can only run in a single process. -% -% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if -% the malt contains {nodes, NodeList} or {processes, X}. If this is not the -% case, a linear fuse is done. -% @spec (Fun, Fuse, List, Malt) -> term() -% Fun = (list()) -> term() -% Fuse = FuseFunc | {recursive, FuseFunc} -% FuseFunc = (term(), term()) -> term() -runmany(Fun, Fuse, List, Malt) when is_list(Malt) -> +%% @doc All of the other functions are implemented with runmany. runmany +%% takes a List, splits it into sublists, and starts processes to operate on +%% each sublist, all done according to Malt. Each process passes its sublist +%% into Fun and sends the result back. +%% +%% The results are then fused together to get the final result. There are two +%% ways this can operate, lineraly and recursively. If Fuse is a function, +%% a fuse is done linearly left-to-right on the sublists, the results +%% of processing the first and second sublists being passed to Fuse, then +%% the result of the first fuse and processing the third sublits, and so on. If +%% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results +%% of processing the second-to-last and last sublists being passed to FuseFunc, +%% then the results of processing the third-to-last sublist and +%% the results of the first fuse, and and so forth. +%% Both methods preserve the original order of the lists elements. +%% +%% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. +%% The recursive fuse makes no guarantee about the order the results of +%% sublists, or the results of fuses are passed to FuseFunc. It +%% continues fusing pairs of results until it is down to one. +%% +%% Recursive fuse is down in parallel with processing the sublists, and a +%% process is spawned to fuse each pair of results. It is a parallized +%% algorithm. Linear fuse is done after all results of processing sublists +%% have been collected, and can only run in a single process. +%% +%% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if +%% the malt contains {nodes, NodeList} or {processes, X}. If this is not the +%% case, a linear fuse is done. +-spec runmany/4 :: (fun(([term()]) -> term()), fuse(), list(), malt()) -> term(). +runmany(Fun, Fuse, List, Malt) + when erlang:is_list(Malt) -> runmany(Fun, Fuse, List, local, no_split, Malt); runmany(Fun, Fuse, List, Malt) -> runmany(Fun, Fuse, List, [Malt]). -runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) when is_integer(MaltTerm) -> +runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) + when erlang:is_integer(MaltTerm) -> runmany(Fun, Fuse, List, Nodes, MaltTerm, Malt); -% run a process for each scheduler runmany(Fun, Fuse, List, local, Split, [{processes, schedulers}|Malt]) -> + %% run a process for each scheduler S = erlang:system_info(schedulers), runmany(Fun, Fuse, List, local, Split, [{processes, S}|Malt]); -% Split the list into X sublists, where X is the number of processes runmany(Fun, Fuse, List, local, no_split, [{processes, X}|_]=Malt) -> - L = length(List), - case L rem X of + %% Split the list into X sublists, where X is the number of processes + L = erlang:length(List), + case (L rem X) of 0 -> - runmany(Fun, Fuse, List, local, L div X, Malt); + runmany(Fun, Fuse, List, local, (L / X), Malt); _ -> - runmany(Fun, Fuse, List, local, L div X + 1, Malt) + runmany(Fun, Fuse, List, local, (L / X) + 1, Malt) end; -% run X process on local machine runmany(Fun, Fuse, List, local, Split, [{processes, X}|Malt]) -> + %% run X process on local machine Nodes = lists:duplicate(X, node()), runmany(Fun, Fuse, List, Nodes, Split, Malt); runmany(Fun, Fuse, List, Nodes, Split, [{timeout, X}|Malt]) -> - Parent = self(), - Timer = spawn(fun () -> - receive - stoptimer -> - Parent ! {timerstopped, self()} - after X -> - Parent ! {timerrang, self()}, - receive - stoptimer -> - Parent ! {timerstopped, self()} - end - end - end), - Ans = try runmany(Fun, Fuse, List, Nodes, Split, Malt) + Parent = erlang:self(), + Timer = proc_lib:spawn(fun () -> + receive + stoptimer -> + Parent ! {timerstopped, erlang:self()} + after X -> + Parent ! {timerrang, erlang:self()}, + receive + stoptimer -> + Parent ! {timerstopped, erlang:self()} + end + end + end), + Ans = try + runmany(Fun, Fuse, List, Nodes, Split, Malt) catch - % we really just want the after block, the syntax - % makes this catch necessary. + %% we really just want the after block, the syntax + %% makes this catch necessary. willneverhappen -> nil after - Timer ! stoptimer, - cleanup_timer(Timer) + Timer ! stoptimer, + cleanup_timer(Timer) end, Ans; runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> @@ -592,12 +670,12 @@ runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> end, [], NodeList), runmany(Fun, Fuse, List, Nodes, Split, Malt); -% local recursive fuse, for when we weren't invoked with {processes, X} -% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. runmany(Fun, {recursive, Fuse}, List, local, Split, []) -> + %% local recursive fuse, for when we weren't invoked with {processes, X} + %% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. runmany(Fun, Fuse, List, local, Split, []); -% by default, operate on each element seperately runmany(Fun, Fuse, List, Nodes, no_split, []) -> + %% by default, operate on each element seperately runmany(Fun, Fuse, List, Nodes, 1, []); runmany(Fun, Fuse, List, local, Split, []) -> List2 = splitmany(List, Split), @@ -615,10 +693,10 @@ cleanup_timer(Timer) -> end. schedulers_on_node(Node) -> - case get(plists_schedulers_on_nodes) of + case erlang:get(ec_plists_schedulers_on_nodes) of undefined -> X = determine_schedulers(Node), - put(plists_schedulers_on_nodes, + erlang:put(ec_plists_schedulers_on_nodes, dict:store(Node, X, dict:new())), X; Dict -> @@ -627,17 +705,17 @@ schedulers_on_node(Node) -> dict:fetch(Node, Dict); false -> X = determine_schedulers(Node), - put(plists_schedulers_on_nodes, + erlang:put(ec_plists_schedulers_on_nodes, dict:store(Node, X, Dict)), X end end. determine_schedulers(Node) -> - Parent = self(), - Child = spawn(Node, fun () -> - Parent ! {self(), erlang:system_info(schedulers)} - end), + Parent = erlang:self(), + Child = proc_lib:spawn(Node, fun () -> + Parent ! {self(), erlang:system_info(schedulers)} + end), erlang:monitor(process, Child), receive {Child, X} -> @@ -650,21 +728,22 @@ determine_schedulers(Node) -> 0 end. -% local runmany, for when we weren't invoked with {processes, X} -% or {nodes, NodeList}. Every sublist is processed in parallel. +%% @doc local runmany, for when we weren't invoked with {processes, X} +%% or {nodes, NodeList}. Every sublist is processed in parallel. local_runmany(Fun, Fuse, List) -> Parent = self (), Pids = lists:map(fun (L) -> F = fun () -> - Parent ! - {self (), Fun(L)} + Parent ! {self (), Fun(L)} end, {Pid, _} = erlang:spawn_monitor(F), Pid end, List), - Answers = try lists:map(fun receivefrom/1, Pids) - catch throw:Message -> + Answers = try + lists:map(fun receivefrom/1, Pids) + catch + throw:Message -> {BadPid, Reason} = Message, handle_error(BadPid, Reason, Pids) end, @@ -678,70 +757,74 @@ receivefrom(Pid) -> {Pid, R} -> R; {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> - throw({BadPid, Reason}); + erlang:throw({BadPid, Reason}); {timerrang, _} -> - throw({nil, timeout}) + erlang:throw({nil, timeout}) end. -% Convert List into [{Number, Sublist}] +%% Convert List into [{Number, Sublist}] cluster_runmany(Fun, Fuse, List, Nodes) -> {List2, _} = lists:foldl(fun (X, {L, Count}) -> - {[{Count, X}|L], Count+1} - end, - {[], 0}, List), + {[{Count, X}|L], Count+1} + end, + {[], 0}, List), cluster_runmany(Fun, Fuse, List2, Nodes, [], []). -% Add a pair of results into the TaskList as a fusing task +%% @doc Add a pair of results into the TaskList as a fusing task cluster_runmany(Fun, {recursive, Fuse}, [], Nodes, Running, [{_, R1}, {_, R2}|Results]) -> cluster_runmany(Fun, {recursive, Fuse}, [{fuse, R1, R2}], Nodes, Running, Results); -% recursive fuse done, return result cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], [{_, Result}]) -> + %% recursive fuse done, return result Result; -% edge case where we are asked to do nothing cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], []) -> + %% edge case where we are asked to do nothing []; -% We're done, now we just have to [linear] fuse the results cluster_runmany(_, Fuse, [], _Nodes, [], Results) -> - fuse(Fuse, lists:map(fun ({_, R}) -> R end, + %% We're done, now we just have to [linear] fuse the results + fuse(Fuse, lists:map(fun ({_, R}) -> + R + end, lists:sort(fun ({A, _}, {B, _}) -> A =< B end, lists:reverse(Results)))); -% We have a ready node and a sublist or fuse to be processed, so we start -% a new process cluster_runmany(Fun, Fuse, [Task|TaskList], [N|Nodes], Running, Results) -> - Parent = self(), +%% We have a ready node and a sublist or fuse to be processed, so we start +%% a new process + + Parent = erlang:self(), case Task of {Num, L2} -> Fun2 = fun () -> - Parent ! {self(), Num, Fun(L2)} + Parent ! {erlang:self(), Num, Fun(L2)} end; {fuse, R1, R2} -> {recursive, FuseFunc} = Fuse, Fun2 = fun () -> - Parent ! {self(), fuse, FuseFunc(R1, R2)} + Parent ! {erlang:self(), fuse, FuseFunc(R1, R2)} end end, Fun3 = fun () -> - try Fun2() + try + Fun2() catch - exit:siblingdied -> + exit:siblingdied -> ok; - exit:Reason -> - Parent ! {self(), error, Reason}; - error:R -> - Parent ! {self(), error, {R, erlang:get_stacktrace()}}; - throw:R -> - Parent ! {self(), error, {{nocatch, R}, erlang:get_stacktrace()}} - end + exit:Reason -> + Parent ! {erlang:self(), error, Reason}; + error:R -> + Parent ! {erlang:self(), error, {R, erlang:get_stacktrace()}}; + throw:R -> + Parent ! {erlang:self(), error, {{nocatch, R}, erlang:get_stacktrace()}} + end end, - Pid = spawn(N, Fun3), + Pid = proc_lib:spawn(N, Fun3), erlang:monitor(process, Pid), cluster_runmany(Fun, Fuse, TaskList, Nodes, [{Pid, N, Task}|Running], Results); -% We can't start a new process, but can watch over already running ones cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Running) > 0 -> + %% We can't start a new process, but can watch over already running ones receive {_Pid, error, Reason} -> RunningPids = lists:map(fun ({Pid, _, _}) -> @@ -750,9 +833,10 @@ cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Runnin Running), handle_error(junkvalue, Reason, RunningPids); {Pid, Num, Result} -> - % throw out the exit message, Reason should be - % normal, noproc, or noconnection - receive {'DOWN', _, _, Pid, _Reason} -> + %% throw out the exit message, Reason should be + %% normal, noproc, or noconnection + receive + {'DOWN', _, _, Pid, _Reason} -> nil end, {Running2, FinishedNode, _} = delete_running(Pid, Running, []), @@ -764,16 +848,16 @@ cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Runnin end, Running), handle_error(nil, timeout, RunningPids); - % node failure + %% node failure {'DOWN', _, _, Pid, noconnection} -> {Running2, _DeadNode, Task} = delete_running(Pid, Running, []), cluster_runmany(Fun, Fuse, [Task|TaskList], Nodes, Running2, Results); - % could a noproc exit message come before the message from - % the process? we are assuming it can't. - % this clause is unlikely to get invoked due to cluster_runmany's - % spawned processes. It will still catch errors in mapreduce's - % reduce process, however. + %% could a noproc exit message come before the message from + %% the process? we are assuming it can't. + %% this clause is unlikely to get invoked due to cluster_runmany's + %% spawned processes. It will still catch errors in mapreduce's + %% reduce process, however. {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> RunningPids = lists:map(fun ({Pid, _, _}) -> Pid @@ -781,9 +865,9 @@ cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Runnin Running), handle_error(BadPid, Reason, RunningPids) end; -% We have data, but no nodes either available or occupied cluster_runmany(_, _, [_Non|_Empty], []=_Nodes, []=_Running, _) -> - exit(allnodescrashed). +%% We have data, but no nodes either available or occupied + erlang:exit(allnodescrashed). delete_running(Pid, [{Pid, Node, List}|Running], Acc) -> {Running ++ Acc, Node, List}; @@ -792,12 +876,12 @@ delete_running(Pid, [R|Running], Acc) -> handle_error(BadPid, Reason, Pids) -> lists:foreach(fun (Pid) -> - exit(Pid, siblingdied) + erlang:exit(Pid, siblingdied) end, Pids), lists:foreach(fun (Pid) -> error_cleanup(Pid, BadPid) end, Pids), - exit(Reason). + erlang:exit(Reason). error_cleanup(BadPid, BadPid) -> ok; @@ -817,7 +901,7 @@ normal_cleanup(Pid) -> ok end. -% edge case +%% edge case fuse(_, []) -> []; fuse({reverse, _}=Fuse, Results) -> @@ -833,9 +917,9 @@ fuse(Fuse, [R2|Results], R1) -> fuse(_, [], R) -> R. -% Splits a list into a list of sublists, each of size Size, -% except for the last element which is less if the original list -% could not be evenly divided into Size-sized lists. +%% @doc Splits a list into a list of sublists, each of size Size, +%% except for the last element which is less if the original list +%% could not be evenly divided into Size-sized lists. splitmany(List, Size) -> splitmany(List, [], Size). @@ -845,8 +929,8 @@ splitmany(List, Acc, Size) -> {Top, NList} = split(Size, List), splitmany(NList, [Top|Acc], Size). -% Like lists:split, except it splits a list smaller than its first -% parameter +%% @doc Like lists:split, except it splits a list smaller than its first +%% parameter split(Size, List) -> split(Size, List, []). diff --git a/test/ec_plists_tests.erl b/test/ec_plists_tests.erl new file mode 100644 index 0000000..7acefe6 --- /dev/null +++ b/test/ec_plists_tests.erl @@ -0,0 +1,75 @@ +%%% @copyright Erlware, LLC. +-module(ec_plists_tests). + +-include_lib("eunit/include/eunit.hrl"). + +%%%=================================================================== +%%% Tests +%%%=================================================================== + +map_good_test() -> + Results = ec_plists:map(fun(_) -> + ok + end, + lists:seq(1, 5)), + ?assertMatch([ok, ok, ok, ok, ok], + Results). + +ftmap_good_test() -> + Results = ec_plists:ftmap(fun(_) -> + ok + end, + lists:seq(1, 3)), + ?assertMatch([{value, ok}, {value, ok}, {value, ok}], + Results). + +filter_good_test() -> + Results = ec_plists:filter(fun(X) -> + X == show + end, + [show, show, remove]), + ?assertMatch([show, show], + Results). + +map_timeout_test() -> + ?assertExit(timeout, + ec_plists:map(fun(T) -> + timer:sleep(T), + T + end, + [1, 100], {timeout, 10})). + +ftmap_timeout_test() -> + ?assertExit(timeout, + ec_plists:ftmap(fun(X) -> + timer:sleep(X), + true + end, + [100, 1], {timeout, 10})). + +filter_timeout_test() -> + ?assertExit(timeout, + ec_plists:filter(fun(T) -> + timer:sleep(T), + T == 1 + end, + [1, 100], {timeout, 10})). + +map_bad_test() -> + ?assertExit({{nocatch,test_exception}, _}, + ec_plists:map(fun(_) -> + erlang:throw(test_exception) + end, + lists:seq(1, 5))). + + +ftmap_bad_test() -> + Results = + ec_plists:ftmap(fun(2) -> + erlang:throw(test_exception); + (N) -> + N + end, + lists:seq(1, 5)), + ?assertMatch([{value, 1}, {error,{throw,test_exception}}, {value, 3}, + {value, 4}, {value, 5}] , Results). From 8d300f5d02538733dadbac27add48d95654aeb8f Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 25 Oct 2012 16:36:17 -0500 Subject: [PATCH 053/240] massively expand the documentation in the README Signed-off-by: Jordan Wilberding --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/README.md b/README.md index f2cab01..3a8ed83 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,107 @@ Goals for the project * High Quality * Well Documented * Well Tested + +Currently Available Modules/Systems +------------------------------------ + +### [ec_date](https://github.com/erlware/erlware_commons/blob/master/src/ec_date.erl) + +This module formats erlang dates in the form {{Year, Month, Day}, +{Hour, Minute, Second}} to printable strings, using (almost) +equivalent formatting rules as http://uk.php.net/date, US vs European +dates are disambiguated in the same way as +http://uk.php.net/manual/en/function.strtotime.php That is, Dates in +the m/d/y or d-m-y formats are disambiguated by looking at the +separator between the various components: if the separator is a slash +(/), then the American m/d/y is assumed; whereas if the separator is a +dash (-) or a dot (.), then the European d-m-y format is assumed. To +avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) +dates. + +erlang has no concept of timezone so the following formats are not +implemented: B e I O P T Z formats c and r will also differ slightly + +### [ec_file](https://github.com/erlware/erlware_commons/blob/master/src/ec_file.erl) + +A set of commonly defined helper functions for files that are not +included in stdlib. + +### [ec_plists](https://github.com/erlware/erlware_commons/blob/master/src/ec_plists.erl) + +plists is a drop-in replacement for module lists, making most +list operations parallel. It can operate on each element in parallel, +for IO-bound operations, on sublists in parallel, for taking advantage +of multi-core machines with CPU-bound operations, and across erlang +nodes, for parallizing inside a cluster. It handles errors and node +failures. It can be configured, tuned, and tweaked to get optimal +performance while minimizing overhead. + +Almost all the functions are identical to equivalent functions in +lists, returning exactly the same result, and having both a form with +an identical syntax that operates on each element in parallel and a +form which takes an optional "malt", a specification for how to +parallize the operation. + +fold is the one exception, parallel fold is different from linear +fold. This module also include a simple mapreduce implementation, and +the function runmany. All the other functions are implemented with +runmany, which is as a generalization of parallel list operations. + +### [ec_semver](https://github.com/erlware/erlware_commons/blob/master/src/ec_semver.erl) + +A complete parser for the [semver](http://semver.org/) +standard. Including a complete set of conforming comparison functions. + +### [ec_lists](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_lists.erl) + +A set of additional list manipulation functions designed to supliment +the `lists` module in stdlib. + +### [ec_talk](https://github.com/erlware/erlware_commons/blob/master/src/ec_talk.erl) + +A set of simple utility functions to falicitate command line +communication with a user. + +Signatures +----------- + +Other languages, have built in support for **Interface** or +**signature** functionality. Java has Interfaces, SML has +Signatures. Erlang, though, doesn't currently support this model, at +least not directly. There are a few ways you can approximate it. We +have defined a mechnism called *signatures* and several modules that +to serve as examples and provide a good set of *dictionary* +signatures. More information about signatures can be found at +[signature](https://github.com/erlware/erlware_commons/blob/master/doc/signatures.md). + + +### [ec_dictionary](https://github.com/erlware/erlware_commons/blob/master/src/ec_dictionary.erl) + +A signature that supports association of keys to values. A map cannot +contain duplicate keys; each key can map to at most one value. + +### [ec_dict](https://github.com/erlware/erlware_commons/blob/master/src/ec_dict.erl) + +This provides an implementation of the ec_dictionary signature using +erlang's dicts as a base. The function documentation for ec_dictionary +applies here as well. + +### [ec_gb_trees](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_gb_trees.erl) + +This provides an implementation of the ec_dictionary signature using +erlang's gb_trees as a base. The function documentation for +ec_dictionary applies here as well. + +### [ec_orddict](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_orddict.erl) + +This provides an implementation of the ec_dictionary signature using +erlang's orddict as a base. The function documentation for +ec_dictionary applies here as well. + +### [ec_rbdict](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_rbdict.erl) + +This provides an implementation of the ec_dictionary signature using +Robert Virding's rbdict module as a base. The function documentation +for ec_dictionary applies here as well. From 95f723e1e043eaa948807c9e5572d9f948ad3585 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 3 Dec 2012 11:15:52 -0500 Subject: [PATCH 054/240] make erlware_commons work on pre-R15 releases Signed-off-by: Jordan Wilberding --- .travis.yml | 6 ++++-- Makefile | 4 ++-- rebar.config.script | 15 +++++++++++++++ src/ec_dictionary.erl | 23 +++++++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 rebar.config.script diff --git a/.travis.yml b/.travis.yml index 35c5897..efd1082 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,11 @@ -language: erlang +=nlanguage: erlang otp_release: - R15B02 - R15B01 - R15B - + - R14B04 + - R14B03 + - R14B02 before_script: "make get-deps" script: "make" branches: diff --git a/Makefile b/Makefile index ab8b307..538bc3e 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ $(ERLWARE_COMMONS_PLT): --apps erts kernel stdlib eunit -r deps dialyzer: $(ERLWARE_COMMONS_PLT) - dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src + dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions -r ./ebin typer: typer --plt $(ERLWARE_COMMONS_PLT) -r ./src @@ -64,4 +64,4 @@ distclean: clean rm -rf $(ERLWARE_COMMONS_PLT) rm -rvf $(CURDIR)/deps/* -rebuild: distclean all +rebuild: distclean get-deps all diff --git a/rebar.config.script b/rebar.config.script new file mode 100644 index 0000000..1d5996c --- /dev/null +++ b/rebar.config.script @@ -0,0 +1,15 @@ +{match, [ErtsNumber]} = re:run("R15B02", "R(\\d+).+", [{capture, [1], list}]), +ErtsVsn = erlang:list_to_integer(ErtsNumber), +Opts1 = case lists:keysearch(erl_opts, 1, CONFIG) of + {value, {erl_opts, Opts0}} -> + Opts0; + false -> + [] + end, +Opts2 = if + ErtsVsn >= 15 -> + [{d, have_callback_support} | Opts1]; + true -> + Opts1 + end, +lists:keystore(erl_opts, 1, CONFIG, {erl_opts, Opts2}). diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl index 1061665..416df72 100644 --- a/src/ec_dictionary.erl +++ b/src/ec_dictionary.erl @@ -41,6 +41,8 @@ -type key(T) :: T. -type value(T) :: T. +-ifdef(have_callback_support). + -callback new() -> any(). -callback has_key(key(any()), any()) -> boolean(). -callback get(key(any()), any()) -> any(). @@ -52,6 +54,27 @@ -callback from_list([{key(any()), value(any())}]) -> any(). -callback keys(any()) -> [key(any())]. +-else. + +%% In the case where R14 or lower is being used to compile the system +%% we need to export a behaviour info +-export([behaviour_info/1]). +-spec behaviour_info(atom()) -> [{atom(), arity()}] | undefined. +behaviour_info(callbacks) -> + [{new, 0}, + {has_key, 2}, + {get, 2}, + {add, 3}, + {remove, 2}, + {has_value, 2}, + {size, 1}, + {to_list, 1}, + {from_list, 1}, + {keys, 1}]; +behaviour_info(_Other) -> + undefined. +-endif. + %%%=================================================================== %%% API %%%=================================================================== From 407ccf886f0234bc0ddadc17f5bf7885fc0d4344 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 3 Dec 2012 11:16:55 -0500 Subject: [PATCH 055/240] support printing erl_syntax meta calls in the same way as erl source Signed-off-by: Jordan Wilberding --- src/ec_compile.erl | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/ec_compile.erl b/src/ec_compile.erl index 482bdb3..6c15520 100644 --- a/src/ec_compile.erl +++ b/src/ec_compile.erl @@ -13,9 +13,11 @@ erl_source_to_core_ast/1, erl_source_to_erl_ast/1, erl_source_to_asm/1, + erl_source_to_erl_syntax/1, erl_string_to_core_ast/1, erl_string_to_erl_ast/1, - erl_string_to_asm/1]). + erl_string_to_asm/1, + erl_string_to_erl_syntax/1]). %%%=================================================================== %%% API @@ -33,13 +35,13 @@ beam_to_erl_source(BeamFName, ErlFName) -> case beam_lib:chunks(BeamFName, [abstract_code]) of {ok, {_, [{abstract_code, {raw_abstract_v1,Forms}}]}} -> - Src = - erl_prettypr:format(erl_syntax:form_list(tl(Forms))), - {ok, Fd} = file:open(ErlFName, [write]), - io:fwrite(Fd, "~s~n", [Src]), - file:close(Fd); - Error -> - Error + Src = + erl_prettypr:format(erl_syntax:form_list(tl(Forms))), + {ok, Fd} = file:open(ErlFName, [write]), + io:fwrite(Fd, "~s~n", [Src]), + file:close(Fd); + Error -> + Error end. %% @doc compile an erlang source file into a Core Erlang AST @@ -67,6 +69,15 @@ erl_source_to_asm(Path) -> {ok, Contents} = file:read_file(Path), erl_string_to_asm(binary_to_list(Contents)). +%% @doc compile an erlang source file to a string that displays the +%% 'erl_syntax1 calls needed to reproduce those terms. +%% +%% @param Path - The path to the erlang source file +-spec erl_source_to_erl_syntax(file:filename()) -> string(). +erl_source_to_erl_syntax(Path) -> + {ok, Contents} = file:read_file(Path), + erl_string_to_erl_syntax(Contents). + %% @doc compile a string representing an erlang expression into an %% Erlang AST %% @@ -105,3 +116,16 @@ erl_string_to_core_ast(StringExpr) -> -spec erl_string_to_asm(string()) -> ErlangAsm::term(). erl_string_to_asm(StringExpr) -> compile:forms(erl_string_to_erl_ast(StringExpr), ['S']). + +%% @doc compile an erlang source file to a string that displays the +%% 'erl_syntax1 calls needed to reproduce those terms. +%% +%% @param StringExpr - The string representing the erlang code. +-spec erl_string_to_erl_syntax(string() | binary()) -> string(). +erl_string_to_erl_syntax(BinaryExpr) + when erlang:is_binary(BinaryExpr) -> + erlang:binary_to_list(BinaryExpr); +erl_string_to_erl_syntax(StringExpr) -> + {ok, Tokens, _} = erl_scan:string(StringExpr), + {ok, ErlAST} = erl_parse:parse_form(Tokens), + io:format(erl_prettypr:format(erl_syntax:meta(ErlAST))). From 74b0d7318dffa635f21b6beb4ebee46833179337 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 17 Jan 2013 14:20:05 -0800 Subject: [PATCH 056/240] support parsing a version with a leading 'v' This *should* make version parsing much, much simpler. --- src/ec_semver.erl | 33 +++++++++++++++++++++++++-------- src/ec_semver_parser.peg | 2 +- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/ec_semver.erl b/src/ec_semver.erl index ac810e5..5855c23 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -1,4 +1,3 @@ - %%%------------------------------------------------------------------- %%% @copyright (C) 2011, Erlware LLC %%% @doc @@ -211,14 +210,18 @@ internal_parse_version([MMP, AlphaPart, BuildPart, _]) -> %% @doc helper function for the peg grammer to parse the iolist into a major_minor_patch -spec parse_major_minor_patch_minpatch(iolist()) -> major_minor_patch_minpatch(). parse_major_minor_patch_minpatch([MajVsn, [], [], []]) -> - MajVsn; + strip_maj_version(MajVsn); parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [], []]) -> - {MajVsn, MinVsn}; -parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn], []]) -> - {MajVsn, MinVsn, PatchVsn}; -parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], - [<<".">>, PatchVsn], [<<".">>, MinPatch]]) -> - {MajVsn, MinVsn, PatchVsn, MinPatch}. + {strip_maj_version(MajVsn), MinVsn}; +parse_major_minor_patch_minpatch([MajVsn, + [<<".">>, MinVsn], + [<<".">>, PatchVsn], []]) -> + {strip_maj_version(MajVsn), MinVsn, PatchVsn}; +parse_major_minor_patch_minpatch([MajVsn, + [<<".">>, MinVsn], + [<<".">>, PatchVsn], + [<<".">>, MinPatch]]) -> + {strip_maj_version(MajVsn), MinVsn, PatchVsn, MinPatch}. %% @doc helper function for the peg grammer to parse the iolist into an alpha part -spec parse_alpha_part(iolist()) -> [alpha_part()]. @@ -245,6 +248,14 @@ format_alpha_part([<<".">>, AlphaPart]) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec strip_maj_version(iolist()) -> version_element(). +strip_maj_version([<<"v">>, MajVsn]) -> + MajVsn; +strip_maj_version([[], MajVsn]) -> + MajVsn; +strip_maj_version(MajVsn) -> + MajVsn. + -spec to_list(integer() | binary() | string()) -> string() | binary(). to_list(Detail) when erlang:is_integer(Detail) -> erlang:integer_to_list(Detail); @@ -308,8 +319,12 @@ internal_pes(Vsn, LVsn) -> eql_test() -> ?assertMatch(true, eql("1.0.0-alpha", "1.0.0-alpha")), + ?assertMatch(true, eql("v1.0.0-alpha", + "1.0.0-alpha")), ?assertMatch(true, eql("1", "1.0.0")), + ?assertMatch(true, eql("v1", + "v1.0.0")), ?assertMatch(true, eql("1.0", "1.0.0")), ?assertMatch(true, eql("1.0.0", @@ -322,6 +337,8 @@ eql_test() -> "1.0.0-alpha.1+build.1")), ?assertMatch(true, eql("1.0-alpha.1+build.1", "1.0.0.0-alpha.1+build.1")), + ?assertMatch(true, eql("1.0-alpha.1+build.1", + "v1.0.0.0-alpha.1+build.1")), ?assertMatch(true, eql("aa", "aa")), ?assertMatch(true, eql("AA.BB", "AA.BB")), ?assertMatch(true, eql("BBB-super", "BBB-super")), diff --git a/src/ec_semver_parser.peg b/src/ec_semver_parser.peg index 09779ae..1210ff9 100644 --- a/src/ec_semver_parser.peg +++ b/src/ec_semver_parser.peg @@ -1,7 +1,7 @@ semver <- major_minor_patch_min_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !. ` ec_semver:internal_parse_version(Node) ` ; -major_minor_patch_min_patch <- version_part ("." version_part)? ("." version_part)? ("." version_part)? ; +major_minor_patch_min_patch <- ("v"? numeric_part / alpha_part) ("." version_part)? ("." version_part)? ("." version_part)? ; version_part <- numeric_part / alpha_part ; From 21c5f9fc74f36e311c35d231e3123b893c328bf6 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Wed, 19 Dec 2012 01:32:53 +0000 Subject: [PATCH 057/240] Added parsing of ISO formats i.e. "2012-12-19T12:12:12.00001" Signed-off-by: Eric Merritt --- src/ec_date.erl | 132 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 14 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 8d79c34..16a0af7 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -42,9 +42,11 @@ -type hour() :: 0..23. -type minute() :: 0..59. -type second() :: 0..59. +-type microsecond() :: 0..1000000. + -type daynum() :: 1..7. -type date() :: {year(),month(),day()}. --type time() :: {hour(),minute(),second()}. +-type time() :: {hour(),minute(),second()} |{hour(),minute(),second(), microsecond()}. -type datetime() :: {date(),time()}. -type now() :: {integer(),integer(),integer()}. @@ -59,8 +61,9 @@ format(Format) -> -spec format(string(),datetime() | now()) -> string(). %% @doc format Date as Format -format(Format, {_,_,_}=Now) -> - format(Format, calendar:now_to_datetime(Now), []); +format(Format, {_,_,Ms}=Now) -> + {Date,{H,M,S}} = calendar:now_to_datetime(Now), + format(Format, {Date, {H,M,S,Ms}}, []); format(Format, Date) -> format(Format, Date, []). @@ -70,6 +73,7 @@ parse(Date) -> do_parse(Date, calendar:universal_time(),[]). -spec parse(string(),datetime() | now()) -> datetime(). + %% @doc parses the datetime from a string parse(Date, {_,_,_}=Now) -> do_parse(Date, calendar:now_to_datetime(Now), []); @@ -88,22 +92,61 @@ do_parse(Date, Now, Opts) -> true -> {D1, T1}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; - _ -> erlang:throw({?MODULE, {bad_date, Date}}) + {D1, _T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} + when is_number(Y), is_number(M), + is_number(D), is_number(H), + is_number(M1), is_number(S), + is_number(Ms) -> + case calendar:valid_date(D1) of + true -> {D1, {H,M1,S,Ms}}; + false -> erlang:throw({?MODULE, {bad_date, Date}}) + end; + Unknown -> erlang:throw({?MODULE, {bad_date, Date, Unknown }}) end. -spec nparse(string()) -> now(). %% @doc parses the datetime from a string into 'now' format nparse(Date) -> - DateTime = parse(Date), - GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), - ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1000000, ESeconds rem 1000000, 0}. - + case parse(Date) of + {DateS, {H, M, S, Ms} } -> + GSeconds = calendar:datetime_to_gregorian_seconds({DateS, {H, M, S} }), + ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, + {ESeconds div 1000000, ESeconds rem 1000000, Ms}; + DateTime -> + GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), + ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, + {ESeconds div 1000000, ESeconds rem 1000000, 0} + end. %% %% LOCAL FUNCTIONS %% + +%% Date/Times 22 Aug 2008 6:35.0001 PM +parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso + (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; +parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_us_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; +parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_world_sep(X) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; + +parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) + when (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour,[]), Min, Sec}, {Ms}}; +parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) + when ?is_us_sep(X) -> + {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, {Ms}}; +parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms ], _Now, _Opts) + when ?is_world_sep(X) -> + {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, {Ms}}; + %% Times - 21:45, 13:45:54, 13:15PM etc parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> {Date, {hour(Hour, PAM), Min, Sec}}; @@ -138,7 +181,8 @@ parse([Month,X,Day,X,Year,Hour | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso ?is_us_sep(X) -> {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; -%% Time is "6:35 PM" + +%% Time is "6:35 PM" ms return parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) @@ -164,7 +208,6 @@ parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso ?is_world_sep(X) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; - parse([Day,Month,Year,Hour | PAM], _Now, _Opts) when ?is_meridian(PAM) -> {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; @@ -181,9 +224,18 @@ parse(_Tokens, _Now, _Opts) -> tokenise([], Acc) -> lists:reverse(Acc); +tokenise([N1, N2, N3, N4, N5, N6 | Rest], Acc) + when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5), ?is_num(N6) -> + tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5, N6]) | Acc]); +tokenise([N1, N2, N3, N4, N5 | Rest], Acc) + when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5) -> + tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5]) | Acc]); tokenise([N1, N2, N3, N4 | Rest], Acc) when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4) -> tokenise(Rest, [ ltoi([N1, N2, N3, N4]) | Acc]); +tokenise([N1, N2, N3 | Rest], Acc) + when ?is_num(N1), ?is_num(N2), ?is_num(N3) -> + tokenise(Rest, [ ltoi([N1, N2, N3]) | Acc]); tokenise([N1, N2 | Rest], Acc) when ?is_num(N1), ?is_num(N2) -> tokenise(Rest, [ ltoi([N1, N2]) | Acc]); @@ -264,6 +316,8 @@ tokenise("TH"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("ND"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("ST"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("OF"++Rest, Acc) -> tokenise(Rest, Acc); +tokenise("T"++Rest, Acc) -> tokenise(Rest, Acc); % 2012-12-12T12:12:12 ISO formatting. +tokenise([$. | Rest], Acc) -> tokenise(Rest, [$. | Acc]); % 2012-12-12T12:12:12.xxxx ISO formatting. tokenise([Else | Rest], Acc) -> tokenise(Rest, [{bad_token, Else} | Acc]). @@ -329,13 +383,13 @@ format([$z|T], {Date,_}=Dt, Acc) -> format(T, Dt, [itol(days_in_year(Date))|Acc]); %% Time Formats -format([$a|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> +format([$a|T], Dt={_,{H,_,_}}, Acc) when H > 12 -> format(T, Dt, ["pm"|Acc]); -format([$a|T], Dt, Acc) -> +format([$a|T], Dt={_,{_,_,_}}, Acc) -> format(T, Dt, ["am"|Acc]); format([$A|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> format(T, Dt, ["PM"|Acc]); -format([$A|T], Dt, Acc) -> +format([$A|T], Dt={_,{_,_,_}}, Acc) -> format(T, Dt, ["AM"|Acc]); format([$g|T], {_,{H,_,_}}=Dt, Acc) when H == 12; H == 0 -> format(T, Dt, ["12"|Acc]); @@ -355,6 +409,38 @@ format([$i|T], {_,{_,M,_}}=Dt, Acc) -> format(T, Dt, [pad2(M)|Acc]); format([$s|T], {_,{_,_,S}}=Dt, Acc) -> format(T, Dt, [pad2(S)|Acc]); +format([$f|T], {_,{_,_,_}}=Dt, Acc) -> + format(T, Dt, [itol(0)|Acc]); + +%% Time Formats ms +format([$a|T], Dt={_,{H,_,_,_}}, Acc) when H > 12 -> + format(T, Dt, ["pm"|Acc]); +format([$a|T], Dt={_,{_,_,_,_}}, Acc) -> + format(T, Dt, ["am"|Acc]); +format([$A|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, ["PM"|Acc]); +format([$A|T], Dt={_,{_,_,_,_}}, Acc) -> + format(T, Dt, ["AM"|Acc]); +format([$g|T], {_,{H,_,_,_}}=Dt, Acc) when H == 12; H == 0 -> + format(T, Dt, ["12"|Acc]); +format([$g|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, [itol(H-12)|Acc]); +format([$g|T], {_,{H,_,_,_}}=Dt, Acc) -> + format(T, Dt, [itol(H)|Acc]); +format([$G|T], {_,{H,_,_,_}}=Dt, Acc) -> + format(T, Dt, [itol(H)|Acc]); +format([$h|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> + format(T, Dt, [pad2(H-12)|Acc]); +format([$h|T], {_,{H,_,_,_}}=Dt, Acc) -> + format(T, Dt, [pad2(H)|Acc]); +format([$H|T], {_,{H,_,_,_}}=Dt, Acc) -> + format(T, Dt, [pad2(H)|Acc]); +format([$i|T], {_,{_,M,_,_}}=Dt, Acc) -> + format(T, Dt, [pad2(M)|Acc]); +format([$s|T], {_,{_,_,S,_}}=Dt, Acc) -> + format(T, Dt, [pad2(S)|Acc]); +format([$f|T], {_,{_,_,_,Ms}}=Dt, Acc) -> + format(T, Dt, [itol(Ms)|Acc]); %% Whole Dates format([$c|T], {{Y,M,D},{H,Min,S}}=Dt, Acc) -> @@ -519,6 +605,7 @@ ltoi(X) -> -include_lib("eunit/include/eunit.hrl"). -define(DATE, {{2001,3,10},{17,16,17}}). +-define(DATEMS, {{2001,3,10},{17,16,17,123456}}). -define(ISO, "o \\WW"). basic_format_test_() -> @@ -674,3 +761,20 @@ iso_test_() -> ?_assertEqual("2009 W53",format(?ISO,{{2009,12,31},{1,1,1}})), ?_assertEqual("2009 W53",format(?ISO,{{2010,1,3}, {1,1,1}})) ]. + +ms_test_() -> + Now=now(), + [ + ?_assertEqual({{2012,12,12}, {12,12,12,1234}}, parse("2012-12-12T12:12:12.1234")), + ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS), + "17:03:17.123456 m is month"), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",?DATEMS), + "2001-03-10T17:16:17.123456"), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), + "2001-03-10T05:16:17.123456"), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), + "2001-03-10T05:16:17.123456"), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.123456")), + "2001-03-10T15:16:17.123456"), + ?_assertEqual(Now, nparse(format("Y-m-d\\TH:i:s.f", Now))) + ]. From 5429ec2d146d68e0c4ee13c2dae343b63f473687 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Fri, 11 Jan 2013 12:02:24 -0800 Subject: [PATCH 058/240] Point rebar to fix of proper library for eunit. Signed-off-by: Eric Merritt --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 08863d2..57dc49a 100644 --- a/rebar.config +++ b/rebar.config @@ -3,7 +3,7 @@ %% Dependencies ================================================================ {deps, [{neotoma, "", {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, - {proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}, + {proper, "", {git, "https://github.com/bkearns/proper.git", {branch, master}}}, {rebar_vsn_plugin, ".*", {git, "https://github.com/erlware/rebar_vsn_plugin.git", {branch, "master"}}}]}. From e28130d9f39857f57843dcb2f5b699c2bd6a4812 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Wed, 19 Dec 2012 01:32:53 +0000 Subject: [PATCH 059/240] Added parsing of ISO formats i.e. "2012-12-19T12:12:12.00001" Conflicts: src/ec_date.erl --- src/ec_date.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 16a0af7..a000763 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -92,13 +92,13 @@ do_parse(Date, Now, Opts) -> true -> {D1, T1}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; - {D1, _T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} + {D1, T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} when is_number(Y), is_number(M), is_number(D), is_number(H), is_number(M1), is_number(S), - is_number(Ms) -> + is_number(Ms) -> case calendar:valid_date(D1) of - true -> {D1, {H,M1,S,Ms}}; + true -> {D1, T1, {Ms}}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; Unknown -> erlang:throw({?MODULE, {bad_date, Date, Unknown }}) @@ -108,14 +108,14 @@ do_parse(Date, Now, Opts) -> %% @doc parses the datetime from a string into 'now' format nparse(Date) -> case parse(Date) of - {DateS, {H, M, S, Ms} } -> - GSeconds = calendar:datetime_to_gregorian_seconds({DateS, {H, M, S} }), - ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1000000, ESeconds rem 1000000, Ms}; - DateTime -> - GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), - ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1000000, ESeconds rem 1000000, 0} + {DateS, Time, {Ms} } -> + GSeconds = calendar:datetime_to_gregorian_seconds({DateS, Time}), + ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, + {ESeconds div 1000000, ESeconds rem 1000000, Ms}; + DateTime -> + GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), + ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, + {ESeconds div 1000000, ESeconds rem 1000000, {0}} end. %% From 5c6af5c7f5d8b06fd2d5bfeacd6657af45e8fcba Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Wed, 19 Dec 2012 21:13:31 +0000 Subject: [PATCH 060/240] Added dializer fix for new date format. Conflicts: src/ec_date.erl --- src/ec_date.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index a000763..3e705c2 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -72,8 +72,7 @@ format(Format, Date) -> parse(Date) -> do_parse(Date, calendar:universal_time(),[]). --spec parse(string(),datetime() | now()) -> datetime(). - +-spec parse(string(),datetime() | now()) -> datetime()|now(). %% @doc parses the datetime from a string parse(Date, {_,_,_}=Now) -> do_parse(Date, calendar:now_to_datetime(Now), []); From 3437fc8c1c0705bf23f843b32f3a7fe0613cc290 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Wed, 19 Dec 2012 21:54:07 +0000 Subject: [PATCH 061/240] Another fix for spec messages. Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 3e705c2..e0c7d64 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -72,7 +72,8 @@ format(Format, Date) -> parse(Date) -> do_parse(Date, calendar:universal_time(),[]). --spec parse(string(),datetime() | now()) -> datetime()|now(). +-spec parse(string(),datetime() | now()) -> datetime(); + (string(),datetime() | now()) -> now(). %% @doc parses the datetime from a string parse(Date, {_,_,_}=Now) -> do_parse(Date, calendar:now_to_datetime(Now), []); From 5beeb3ff1b9d4ee33b1d5a67e0cf00c3bd518496 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Wed, 19 Dec 2012 23:13:11 +0000 Subject: [PATCH 062/240] Fix for dializer error. Conflicts: src/ec_date.erl --- src/ec_date.erl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index e0c7d64..240e14b 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -72,8 +72,8 @@ format(Format, Date) -> parse(Date) -> do_parse(Date, calendar:universal_time(),[]). --spec parse(string(),datetime() | now()) -> datetime(); - (string(),datetime() | now()) -> now(). +-spec parse(string(),datetime() | now()) -> datetime(). + %% @doc parses the datetime from a string parse(Date, {_,_,_}=Now) -> do_parse(Date, calendar:now_to_datetime(Now), []); @@ -92,13 +92,13 @@ do_parse(Date, Now, Opts) -> true -> {D1, T1}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; - {D1, T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} + {D1, _T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} when is_number(Y), is_number(M), is_number(D), is_number(H), is_number(M1), is_number(S), is_number(Ms) -> case calendar:valid_date(D1) of - true -> {D1, T1, {Ms}}; + true -> {D1, {H,M1,S,Ms}}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; Unknown -> erlang:throw({?MODULE, {bad_date, Date, Unknown }}) @@ -108,14 +108,14 @@ do_parse(Date, Now, Opts) -> %% @doc parses the datetime from a string into 'now' format nparse(Date) -> case parse(Date) of - {DateS, Time, {Ms} } -> - GSeconds = calendar:datetime_to_gregorian_seconds({DateS, Time}), + {DateS, {H, M, S, Ms} } -> + GSeconds = calendar:datetime_to_gregorian_seconds({DateS, {H, M, S} }), ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, {ESeconds div 1000000, ESeconds rem 1000000, Ms}; DateTime -> GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1000000, ESeconds rem 1000000, {0}} + {ESeconds div 1000000, ESeconds rem 1000000, 0} end. %% From 5b23329d3a4ac128580671dd94e87d262761ea7d Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Thu, 20 Dec 2012 02:07:51 +0000 Subject: [PATCH 063/240] Added tests and validated parse->format->parse and nparse->format->nparse Conflicts: src/ec_date.erl --- src/ec_date.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 240e14b..0f47102 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -768,13 +768,11 @@ ms_test_() -> ?_assertEqual({{2012,12,12}, {12,12,12,1234}}, parse("2012-12-12T12:12:12.1234")), ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS), "17:03:17.123456 m is month"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",?DATEMS), - "2001-03-10T17:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), + ?_assertEqual(format("Y-m-d\\Th:i:s.f",?DATEMS), "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), + ?_assertEqual(format("Y-m-d\\Th:i:s.f",nparse("2001-03-10T05:16:17.123456")), "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.123456")), - "2001-03-10T15:16:17.123456"), - ?_assertEqual(Now, nparse(format("Y-m-d\\TH:i:s.f", Now))) + ?_assertEqual(format("Y-m-d\\Th:i:s.f",nparse("2001-03-10T05:16:17.123456")), + "2001-03-10T05:16:17.123456"), + ?_assertEqual(Now, nparse(format("Y-m-d\\Th:i:s.f", Now))) ]. From 122af09cb179f0a518959512177cffc7c39f4300 Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Thu, 20 Dec 2012 17:22:04 +0000 Subject: [PATCH 064/240] Added more tests and fixed format string to be 24 hour vs 12 hour. Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 0f47102..4bf2200 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -768,11 +768,13 @@ ms_test_() -> ?_assertEqual({{2012,12,12}, {12,12,12,1234}}, parse("2012-12-12T12:12:12.1234")), ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS), "17:03:17.123456 m is month"), - ?_assertEqual(format("Y-m-d\\Th:i:s.f",?DATEMS), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",?DATEMS), "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\Th:i:s.f",nparse("2001-03-10T05:16:17.123456")), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\Th:i:s.f",nparse("2001-03-10T05:16:17.123456")), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), "2001-03-10T05:16:17.123456"), + ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.123456")), + "2001-03-10T15:16:17.123456"), ?_assertEqual(Now, nparse(format("Y-m-d\\Th:i:s.f", Now))) ]. From 4558635813b1804a78b44286be0d981cfb805f0f Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Thu, 20 Dec 2012 17:31:25 +0000 Subject: [PATCH 065/240] Fix broken tests. Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 4bf2200..240e14b 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -769,12 +769,12 @@ ms_test_() -> ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS), "17:03:17.123456 m is month"), ?_assertEqual(format("Y-m-d\\TH:i:s.f",?DATEMS), - "2001-03-10T05:16:17.123456"), + "2001-03-10T17:16:17.123456"), ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), "2001-03-10T05:16:17.123456"), ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), "2001-03-10T05:16:17.123456"), ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.123456")), "2001-03-10T15:16:17.123456"), - ?_assertEqual(Now, nparse(format("Y-m-d\\Th:i:s.f", Now))) + ?_assertEqual(Now, nparse(format("Y-m-d\\TH:i:s.f", Now))) ]. From 320813e56e63ad965d26e4fcc8a881be4cecefde Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Mon, 21 Jan 2013 14:41:50 -0800 Subject: [PATCH 066/240] Fixed type-o in .travis.yml Signed-off-by: Jordan Wilberding --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index efd1082..745f994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -=nlanguage: erlang +language: erlang otp_release: - R15B02 - R15B01 From 97d39ec8db06a29ffc59d9d23816a54049e69eeb Mon Sep 17 00:00:00 2001 From: Ben Kearns Date: Thu, 24 Jan 2013 11:58:04 -0800 Subject: [PATCH 067/240] Added support for ISO8601 Zulu and TZ time zone support. Remove hard coded version string in rebar.config.script for unit test pass. Remove dializer and edoc from default target to enable tests to run on Travis-ci Signed-off-by: Jordan Wilberding --- Makefile | 45 ++++++++++++++++++++++++++++++++------------- rebar.config.script | 6 +++--- src/ec_date.erl | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 538bc3e..51727d2 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ # BSD License see COPYING ERL = $(shell which erl) +ERL_VER = $(shell erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell) ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/*/ebin @@ -14,10 +15,9 @@ endif ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt -.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps \ - rebuild +.PHONY: all compile doc clean test shell distclean pdf get-deps rebuild #dialyzer typer #fail on Travis. -all: compile dialyzer doc test +all: compile doc test #dialyzer #fail on travis get-deps: $(REBAR) get-deps @@ -27,22 +27,41 @@ compile: $(REBAR) skip_deps=true compile doc: compile - $(REBAR) skip_deps=true doc + - $(REBAR) skip_deps=true doc test: compile $(REBAR) skip_deps=true eunit -$(ERLWARE_COMMONS_PLT): - @echo Building local plt at $(ERLWARE_COMMONS_PLT) +$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts: + @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - - dialyzer --fullpath --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \ - --apps erts kernel stdlib eunit -r deps -dialyzer: $(ERLWARE_COMMONS_PLT) - dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions -r ./ebin + - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + --apps erts -typer: - typer --plt $(ERLWARE_COMMONS_PLT) -r ./src +$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel:$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts + @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base + @echo + - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + --apps kernel + +$(ERLWARE_COMMONS_PLT).$(ERL_VER).base:$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel + @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base + @echo + - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + --apps stdlib + +$(ERLWARE_COMMONS_PLT).$(ERL_VER): $(ERLWARE_COMMONS_PLT).$(ERL_VER).base + @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER) + @echo + - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) --add_to_plt --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base \ + --apps eunit -r deps + +dialyzer: $(ERLWARE_COMMONS_PLT).$(ERL_VER) + dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -Wrace_conditions -r ./ebin + +typer: $(ERLWARE_COMMONS_PLT).$(ERL)VER( + typer --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -r ./src shell: compile # You often want *rebuilt* rebar tests to be available to the @@ -61,7 +80,7 @@ clean: - rm $(CURDIR)/doc/edoc-info distclean: clean - rm -rf $(ERLWARE_COMMONS_PLT) + rm -rf $(ERLWARE_COMMONS_PLT).$(ERL_VER) rm -rvf $(CURDIR)/deps/* rebuild: distclean get-deps all diff --git a/rebar.config.script b/rebar.config.script index 1d5996c..c19a751 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -1,4 +1,4 @@ -{match, [ErtsNumber]} = re:run("R15B02", "R(\\d+).+", [{capture, [1], list}]), +{match, [ErtsNumber]} = re:run(erlang:system_info(otp_release), "R(\\d+).+", [{capture, [1], list}]), ErtsVsn = erlang:list_to_integer(ErtsNumber), Opts1 = case lists:keysearch(erl_opts, 1, CONFIG) of {value, {erl_opts, Opts0}} -> @@ -8,8 +8,8 @@ Opts1 = case lists:keysearch(erl_opts, 1, CONFIG) of end, Opts2 = if ErtsVsn >= 15 -> - [{d, have_callback_support} | Opts1]; - true -> + [{d, have_callback_support} | Opts1]; + true -> Opts1 end, lists:keystore(erl_opts, 1, CONFIG, {erl_opts, Opts2}). diff --git a/src/ec_date.erl b/src/ec_date.erl index 240e14b..b32de88 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -122,6 +122,20 @@ nparse(Date) -> %% LOCAL FUNCTIONS %% +parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $Z ], _Now, _Opts) + when (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, { 0}}; + +parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $+, Off | _Rest ], _Now, _Opts) + when (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour, []) - Off, Min, Sec}, {0}}; + +parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $-, Off | _Rest ], _Now, _Opts) + when (?is_us_sep(X) orelse ?is_world_sep(X)) + andalso Year > 31 -> + {{Year, Month, Day}, {hour(Hour, []) + Off, Min, Sec}, {0}}; %% Date/Times 22 Aug 2008 6:35.0001 PM parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) @@ -317,7 +331,9 @@ tokenise("ND"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("ST"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("OF"++Rest, Acc) -> tokenise(Rest, Acc); tokenise("T"++Rest, Acc) -> tokenise(Rest, Acc); % 2012-12-12T12:12:12 ISO formatting. -tokenise([$. | Rest], Acc) -> tokenise(Rest, [$. | Acc]); % 2012-12-12T12:12:12.xxxx ISO formatting. +tokenise([$Z | Rest], Acc) -> tokenise(Rest, [$Z | Acc]); % 2012-12-12T12:12:12Zulu +tokenise([$. | Rest], Acc) -> tokenise(Rest, [$. | Acc]); % 2012-12-12T12:12:12.xxxx ISO formatting. +tokenise([$+| Rest], Acc) -> tokenise(Rest, [$+ | Acc]); % 2012-12-12T12:12:12.xxxx+ ISO formatting. tokenise([Else | Rest], Acc) -> tokenise(Rest, [{bad_token, Else} | Acc]). @@ -778,3 +794,19 @@ ms_test_() -> "2001-03-10T15:16:17.123456"), ?_assertEqual(Now, nparse(format("Y-m-d\\TH:i:s.f", Now))) ]. + +zulu_test_() -> + [ + ?_assertEqual(format("Y-m-d\\TH:i:sZ",nparse("2001-03-10T15:16:17.123456")), + "2001-03-10T15:16:17Z"), + ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17Z")), + "2001-03-10T15:16:17"), + ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17+04")), + "2001-03-10T11:16:17"), + ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17+04:00")), + "2001-03-10T11:16:17"), + ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04")), + "2001-03-10T19:16:17"), + ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04:00")), + "2001-03-10T19:16:17") + ]. From a2fac85ff656da468d4a309eb266dcf7253ac6fc Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Sun, 17 Feb 2013 16:44:26 -0600 Subject: [PATCH 068/240] Disambiguate parsing "Aug 12" and "12 Aug". This started with just trying to parse the date format: December 21st, 2013 7:00pm, which was failing with a bad_date error. The solution involved setting up "Hinted Months", which was just a term I used to indicate that a month was specified by name (ie "December"), rather than by number (ie, "12"). Previously, named months were simply replaced by their respective numbers in the parser. This tags those named months so that the parser will unambiguously parse them correctly. A tagged "Hinted Month" is simply a tuple with the tag `?MONTH_TAG`. For example: "December" gets converted to `{?MONTH_TAG, 12}` For example: "Aug 12" and "12 Aug". It's clear to the *reader* what is meant, but when converted to simply 8 and 12, the parser has no way of knowing which is which. Doing this was aided with the addition of some macros to help it along, since doing just straight comparisons with the hinted months was yielding unexpected results. For example: `{mon, 1} > 31` returns true, so changing that comparison to an ?is_year/1 macro that does: `is_integer(Y) andalso Y > 31`. It might not be a bad idea to help the parser be *very* unambiguous by putting these macros on all comparisons. Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 135 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 39 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index b32de88..69f3446 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -34,10 +34,16 @@ -define( is_us_sep(X), ( X==$/) ). -define( is_world_sep(X), ( X==$-) ). +-define( MONTH_TAG, month ). +-define( is_year(X), (is_integer(X) andalso X > 31) ). +-define( is_day(X), (is_integer(X) andalso X =< 31) ). +-define( is_hinted_month(X), (is_tuple(X) andalso size(X)=:=2 andalso element(1,X)=:=?MONTH_TAG) ). +-define( is_month(X), ( (is_integer(X) andalso X =< 12) orelse ?is_hinted_month(X) ) ). + -define(GREGORIAN_SECONDS_1970, 62167219200). -type year() :: non_neg_integer(). --type month() :: 1..12. +-type month() :: 1..12 | {?MONTH_TAG, 1..12}. -type day() :: 1..31. -type hour() :: 0..23. -type minute() :: 0..59. @@ -81,7 +87,7 @@ parse(Date, Now) -> do_parse(Date, Now, []). do_parse(Date, Now, Opts) -> - case parse(tokenise(string:to_upper(Date), []), Now, Opts) of + case filter_hints(parse(tokenise(string:to_upper(Date), []), Now, Opts)) of {error, bad_date} -> erlang:throw({?MODULE, {bad_date, Date}}); {D1, T1} = {{Y, M, D}, {H, M1, S}} @@ -104,6 +110,13 @@ do_parse(Date, Now, Opts) -> Unknown -> erlang:throw({?MODULE, {bad_date, Date, Unknown }}) end. +filter_hints({{Y, {?MONTH_TAG, M}, D}, {H, M1, S}}) -> + filter_hints({{Y, M, D}, {H, M1, S}}); +filter_hints({{Y, {?MONTH_TAG, M}, D}, {H, M1, S}, {Ms}}) -> + filter_hints({{Y, M, D}, {H, M1, S}, {Ms}}); +filter_hints(Other) -> + Other. + -spec nparse(string()) -> now(). %% @doc parses the datetime from a string into 'now' format nparse(Date) -> @@ -141,40 +154,61 @@ parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $-, Off | _Rest ], _Now, parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_us_sep(X) -> + when ?is_meridian(PAM) andalso ?is_us_sep(X) + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_world_sep(X) -> + when ?is_meridian(PAM) andalso ?is_world_sep(X) + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour,[]), Min, Sec}, {Ms}}; parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) - when ?is_us_sep(X) -> + when ?is_us_sep(X) andalso ?is_month(Month) -> {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, {Ms}}; parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms ], _Now, _Opts) - when ?is_world_sep(X) -> + when ?is_world_sep(X) andalso ?is_month(Month) -> {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, {Ms}}; +%% Date/Times Dec 1st, 2012 6:25 PM +parse([Month,Day,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; +parse([Month,Day,Year,Hour,$:,Min | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; +parse([Month,Day,Year,Hour | PAM], _Now, _Opts) + when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; + +%% Date/Times Dec 1st, 2012 18:25:15 (no AM/PM) +parse([Month,Day,Year,Hour,$:,Min,$:,Sec], _Now, _Opts) + when ?is_hinted_month(Month) andalso ?is_day(Day) -> + {{Year, Month, Day}, {hour(Hour, []), Min, Sec}}; +parse([Month,Day,Year,Hour,$:,Min], _Now, _Opts) + when ?is_hinted_month(Month) andalso ?is_day(Day) -> + {{Year, Month, Day}, {hour(Hour, []), Min, 0}}; + %% Times - 21:45, 13:45:54, 13:15PM etc parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> {Date, {hour(Hour, PAM), Min, Sec}}; parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> {Date, {hour(Hour, PAM), Min, 0}}; parse([Hour | PAM],{Date,_Time}, _Opts) when ?is_meridian(PAM) -> - {Date, {hour(Hour,PAM), 0, 0}}; + {Date, {hour(Hour,PAM), 0, 0}}; %% Dates 23/april/1963 parse([Day,Month,Year], {_Date, Time}, _Opts) -> {{Year, Month, Day}, Time}; parse([Year,X,Month,X,Day], {_Date, Time}, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, Time}; parse([Month,X,Day,X,Year], {_Date, Time}, _Opts) when ?is_us_sep(X) -> {{Year, Month, Day}, Time}; @@ -186,7 +220,7 @@ parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_world_sep(X) -> parse([Year,X,Month,X,Day,Hour | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; parse([Day,X,Month,X,Year,Hour | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso ?is_world_sep(X) -> @@ -200,7 +234,7 @@ parse([Month,X,Day,X,Year,Hour | PAM], _Date, _Opts) parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso ?is_world_sep(X) -> @@ -213,7 +247,7 @@ parse([Month,X,Day,X,Year,Hour,$:,Min | PAM], _Date, _Opts) parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso ?is_us_sep(X) -> @@ -257,32 +291,37 @@ tokenise([N1 | Rest], Acc) when ?is_num(N1) -> tokenise(Rest, [ ltoi([N1]) | Acc]); -tokenise("JANUARY"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); -tokenise("JAN"++Rest, Acc) -> tokenise(Rest, [1 | Acc]); -tokenise("FEBRUARY"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); -tokenise("FEB"++Rest, Acc) -> tokenise(Rest, [2 | Acc]); -tokenise("MARCH"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); -tokenise("MAR"++Rest, Acc) -> tokenise(Rest, [3 | Acc]); -tokenise("APRIL"++Rest, Acc) -> tokenise(Rest, [4 | Acc]); -tokenise("APR"++Rest, Acc) -> tokenise(Rest, [4 | Acc]); -tokenise("MAY"++Rest, Acc) -> tokenise(Rest, [5 | Acc]); -tokenise("JUNE"++Rest, Acc) -> tokenise(Rest, [6 | Acc]); -tokenise("JUN"++Rest, Acc) -> tokenise(Rest, [6 | Acc]); -tokenise("JULY"++Rest, Acc) -> tokenise(Rest, [7 | Acc]); -tokenise("JUL"++Rest, Acc) -> tokenise(Rest, [7 | Acc]); -tokenise("AUGUST"++Rest, Acc) -> tokenise(Rest, [8 | Acc]); -tokenise("AUG"++Rest, Acc) -> tokenise(Rest, [8 | Acc]); -tokenise("SEPTEMBER"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); -tokenise("SEPT"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); -tokenise("SEP"++Rest, Acc) -> tokenise(Rest, [9 | Acc]); -tokenise("OCTOBER"++Rest, Acc) -> tokenise(Rest, [10 | Acc]); -tokenise("OCT"++Rest, Acc) -> tokenise(Rest, [10 | Acc]); -tokenise("NOVEMBER"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); -tokenise("NOVEM"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); -tokenise("NOV"++Rest, Acc) -> tokenise(Rest, [11 | Acc]); -tokenise("DECEMBER"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); -tokenise("DECEM"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); -tokenise("DEC"++Rest, Acc) -> tokenise(Rest, [12 | Acc]); + +%% Worded Months get tagged with ?MONTH_TAG to let the parser know that these +%% are unambiguously declared to be months. This was there's no confusion +%% between, for example: "Aug 12" and "12 Aug" +%% These hint tags are filtered in filter_hints/1 above. +tokenise("JANUARY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,1} | Acc]); +tokenise("JAN"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,1} | Acc]); +tokenise("FEBRUARY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,2} | Acc]); +tokenise("FEB"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,2} | Acc]); +tokenise("MARCH"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,3} | Acc]); +tokenise("MAR"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,3} | Acc]); +tokenise("APRIL"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,4} | Acc]); +tokenise("APR"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,4} | Acc]); +tokenise("MAY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,5} | Acc]); +tokenise("JUNE"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,6} | Acc]); +tokenise("JUN"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,6} | Acc]); +tokenise("JULY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,7} | Acc]); +tokenise("JUL"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,7} | Acc]); +tokenise("AUGUST"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,8} | Acc]); +tokenise("AUG"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,8} | Acc]); +tokenise("SEPTEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); +tokenise("SEPT"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); +tokenise("SEP"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); +tokenise("OCTOBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,10} | Acc]); +tokenise("OCT"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,10} | Acc]); +tokenise("NOVEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); +tokenise("NOVEM"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); +tokenise("NOV"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); +tokenise("DECEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); +tokenise("DECEM"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); +tokenise("DEC"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); tokenise([$: | Rest], Acc) -> tokenise(Rest, [ $: | Acc]); tokenise([$/ | Rest], Acc) -> tokenise(Rest, [ $/ | Acc]); @@ -505,6 +544,10 @@ to_w(X) -> X. suffix(1) -> "st"; suffix(2) -> "nd"; suffix(3) -> "rd"; +suffix(21) -> "st"; +suffix(22) -> "nd"; +suffix(23) -> "rd"; +suffix(31) -> "st"; suffix(_) -> "th". -spec sdayd(date()) -> string(). @@ -672,6 +715,20 @@ basic_parse_test_() -> parse("22 Aug 2008 6:35 PM", ?DATE)), ?_assertEqual({{2008,8,22}, {18,0,0}}, parse("22 Aug 2008 6 PM", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,0,0}}, + parse("Aug 22, 2008 6 PM", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,0,0}}, + parse("August 22nd, 2008 6:00 PM", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,15,15}}, + parse("August 22nd 2008, 6:15:15pm", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,15,15}}, + parse("August 22nd, 2008, 6:15:15pm", ?DATE)), + ?_assertEqual({{2008,8,22}, {18,15,0}}, + parse("Aug 22nd 2008, 18:15", ?DATE)), + ?_assertEqual({{2012,12,10}, {0,0,0}}, + parse("Dec 10th, 2012, 12:00 AM", ?DATE)), + ?_assertEqual({{2012,12,10}, {0,0,0}}, + parse("10 Dec 2012 12:00 AM", ?DATE)), ?_assertEqual({{2001,3,10}, {11,15,0}}, parse("11:15", ?DATE)), ?_assertEqual({{2001,3,10}, {1,15,0}}, From 4ba12ec4ad5ab9fefd5b8dae33912bc14c47adbb Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Mon, 18 Feb 2013 14:20:13 -0600 Subject: [PATCH 069/240] Add disambig tests, add disambig parsing date-only Signed-off-by: Jordan Wilberding --- src/ec_date.erl | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/ec_date.erl b/src/ec_date.erl index 69f3446..66ffaeb 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -203,6 +203,21 @@ parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> parse([Hour | PAM],{Date,_Time}, _Opts) when ?is_meridian(PAM) -> {Date, {hour(Hour,PAM), 0, 0}}; +%% Dates (Any combination with word month "aug 8th, 2008", "8 aug 2008", "2008 aug 21" "2008 5 aug" ) +%% Will work because of the "Hinted month" +parse([Day,Month,Year], {_Date, Time}, _Opts) + when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> + {{Year, Month, Day}, Time}; +parse([Month,Day,Year], {_Date, Time}, _Opts) + when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> + {{Year, Month, Day}, Time}; +parse([Year,Day,Month], {_Date, Time}, _Opts) + when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> + {{Year, Month, Day}, Time}; +parse([Year,Month,Day], {_Date, Time}, _Opts) + when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> + {{Year, Month, Day}, Time}; + %% Dates 23/april/1963 parse([Day,Month,Year], {_Date, Time}, _Opts) -> {{Year, Month, Day}, Time}; @@ -670,6 +685,11 @@ ltoi(X) -> basic_format_test_() -> [ ?_assertEqual(format("F j, Y, g:i a",?DATE), "March 10, 2001, 5:16 pm"), + ?_assertEqual(format("F jS, Y, g:i a",?DATE), "March 10th, 2001, 5:16 pm"), + ?_assertEqual(format("F jS",{{2011,3,21},{0,0,0}}), "March 21st"), + ?_assertEqual(format("F jS",{{2011,3,22},{0,0,0}}), "March 22nd"), + ?_assertEqual(format("F jS",{{2011,3,23},{0,0,0}}), "March 23rd"), + ?_assertEqual(format("F jS",{{2011,3,31},{0,0,0}}), "March 31st"), ?_assertEqual(format("m.d.y",?DATE), "03.10.01"), ?_assertEqual(format("j, n, Y",?DATE), "10, 3, 2001"), ?_assertEqual(format("Ymd",?DATE), "20010310"), @@ -725,6 +745,50 @@ basic_parse_test_() -> parse("August 22nd, 2008, 6:15:15pm", ?DATE)), ?_assertEqual({{2008,8,22}, {18,15,0}}, parse("Aug 22nd 2008, 18:15", ?DATE)), + ?_assertEqual({{2008,8,2}, {17,16,17}}, + parse("2nd of August 2008", ?DATE)), + ?_assertEqual({{2008,8,2}, {17,16,17}}, + parse("August 2nd, 2008", ?DATE)), + ?_assertEqual({{2008,8,2}, {17,16,17}}, + parse("2nd August, 2008", ?DATE)), + ?_assertEqual({{2008,8,2}, {17,16,17}}, + parse("2008 August 2nd", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,0,0}}, + parse("2-Aug-2008 6 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("2-Aug-2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,12}}, + parse("2-Aug-2008 6:35:12 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,0,0}}, + parse("August/2/2008 6 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("August/2/2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("2 August 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,0,0}}, + parse("2 Aug 2008 6AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("2 Aug 2008 6:35AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("2 Aug 2008 6:35 AM", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,0,0}}, + parse("2 Aug 2008 6", ?DATE)), + ?_assertEqual({{2008,8,2}, {6,35,0}}, + parse("2 Aug 2008 6:35", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,35,0}}, + parse("2 Aug 2008 6:35 PM", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,0,0}}, + parse("2 Aug 2008 6 PM", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,0,0}}, + parse("Aug 2, 2008 6 PM", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,0,0}}, + parse("August 2nd, 2008 6:00 PM", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,15,15}}, + parse("August 2nd 2008, 6:15:15pm", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,15,15}}, + parse("August 2nd, 2008, 6:15:15pm", ?DATE)), + ?_assertEqual({{2008,8,2}, {18,15,0}}, + parse("Aug 2nd 2008, 18:15", ?DATE)), ?_assertEqual({{2012,12,10}, {0,0,0}}, parse("Dec 10th, 2012, 12:00 AM", ?DATE)), ?_assertEqual({{2012,12,10}, {0,0,0}}, From e1e30f4a75f46bd9ac4cbb4b6a92f5c79525e308 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Thu, 14 Mar 2013 11:50:34 -0700 Subject: [PATCH 070/240] add file type discovery and resolution to ec_file --- src/ec_file.erl | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index 45adb2a..5e5d353 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -15,6 +15,8 @@ mkdir_p/1, find/2, is_symlink/1, + type/1, + real_dir_path/1, remove/1, remove/2, md5sum/1, @@ -115,7 +117,31 @@ is_symlink(Path) -> _ -> false end. - +%% @doc returns the type of the file. +-spec type(file:name()) -> file | symlink | directory. +type(Path) -> + case filelib:is_regular(Path) of + true -> + file; + false -> + case is_symlink(Path) of + true -> + symlink; + false -> + directory + end + end. +%% @doc gets the real path of a directory. This is mostly useful for +%% resolving symlinks. Be aware that this temporarily changes the +%% current working directory to figure out what the actual path +%% is. That means that it can be quite slow. +-spec real_dir_path(file:name()) -> file:name(). +real_dir_path(Path) -> + {ok, CurCwd} = file:get_cwd(), + ok = file:set_cwd(Path), + {ok, RealPath} = file:get_cwd(), + ok = file:set_cwd(CurCwd), + filename:absname(RealPath). %% @doc make a unique temorory directory. Similar function to BSD stdlib %% function of the same name. @@ -334,6 +360,21 @@ exists_test() -> ?assertMatch(true, exists(Name1)), ?assertMatch(false, exists(NoName)). +real_path_test() -> + BaseDir = "foo", + Dir = filename:absname(filename:join(BaseDir, "source1")), + LinkDir = filename:join([BaseDir, "link"]), + ok = mkdir_p(Dir), + file:make_symlink(Dir, LinkDir), + ?assertEqual(Dir, real_dir_path(LinkDir)), + ?assertEqual(directory, type(Dir)), + ?assertEqual(symlink, type(LinkDir)), + TermFile = filename:join(BaseDir, "test_file"), + ok = write_term(TermFile, foo), + ?assertEqual(file, type(TermFile)), + ?assertEqual(true, is_symlink(LinkDir)), + ?assertEqual(false, is_symlink(Dir)). + find_test() -> %% Create a directory in /tmp for the test. Clean everything afterwards {BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(), From 17e08c04a2e3aec92d89f983b506244355caee45 Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Tue, 9 Apr 2013 10:50:51 -0700 Subject: [PATCH 071/240] make ec_file a bit more friendly to binary file names --- src/ec_file.erl | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index 5e5d353..c291a81 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -241,7 +241,8 @@ find_in_subdirs(FromDir, TargetPattern) -> end end, [], - filelib:wildcard(filename:join(FromDir, "*"))). + sub_files(FromDir)). + -spec remove_recursive(file:name(), Options::list()) -> ok | {error, Reason::term()}. @@ -252,7 +253,7 @@ remove_recursive(Path, Options) -> true -> lists:foreach(fun(ChildPath) -> remove_recursive(ChildPath, Options) - end, filelib:wildcard(filename:join(Path, "*"))), + end, sub_files(Path)), file:del_dir(Path) end. @@ -273,7 +274,7 @@ copy_subfiles(From, To, Options) -> ChildTo = filename:join([To, filename:basename(ChildFrom)]), copy(ChildFrom, ChildTo, Options) end, - lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). + lists:foreach(Fun, sub_files(From)). -spec make_dir_if_dir(file:name()) -> ok | {error, Reason::term()}. make_dir_if_dir(File) -> @@ -299,6 +300,10 @@ hex0(14) -> $e; hex0(15) -> $f; hex0(I) -> $0 + I. + +sub_files(From) -> + {ok, SubFiles} = file:list_dir(From), + [filename:join(From, SubFile) || SubFile <- SubFiles]. %%%=================================================================== %%% Test Functions %%%=================================================================== @@ -378,10 +383,11 @@ real_path_test() -> find_test() -> %% Create a directory in /tmp for the test. Clean everything afterwards {BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(), - ?assertMatch([Name2, - Name3, - Name1], - find(BaseDir, "file[a-z]+\$")), + Result = find(BaseDir, "file[a-z]+\$"), + ?assertMatch(3, erlang:length(Result)), + ?assert(lists:member(Name1, Result)), + ?assert(lists:member(Name2, Result)), + ?assert(lists:member(Name3, Result)), remove(BaseDir, [recursive]). -endif. From 58e6b0476d75b718a85eefb633bc93ea47fe1606 Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Mon, 8 Apr 2013 18:30:53 -0700 Subject: [PATCH 072/240] support testing on r16 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 745f994..ecf6681 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: erlang otp_release: + - R16B - R15B02 - R15B01 - R15B From a1fc04f2b76f20d0f07d2197aaa14ee6d844960e Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Tue, 9 Apr 2013 15:40:31 -0700 Subject: [PATCH 073/240] Add contributing document --- CONTRIBUTING.md | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e63ac46 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,139 @@ +Contributing +============ + +Introduction +------------ + +This document describes the usages and rules to follow when contributing +to this project. + +It uses the uppercase keywords SHOULD for optional but highly recommended +conditions and MUST for required conditions. + +`git` is a distributed source code versioning system. This document refers +to three different repositories hosting the source code of the project. +`Your local copy` refers to the copy of the repository that you have on +your computer. The remote repository `origin` refers to your fork of the +project's repository that you can find in your GitHub account. The remote +repository `upstream` refers to the official repository for this project. + +Reporting bugs +-------------- + +Upon identifying a bug you SHOULD submit a ticket, regardless of your +plan for fixing it. If you plan to fix the bug, you SHOULD discuss your +plans to avoid having your work rejected. + +Before implementing a new feature, you SHOULD submit a ticket for discussion +on your plans. The feature might have been rejected already, or the +implementation might already be decided. + +Cloning +------- + +You MUST fork the project's repository to your GitHub account by clicking +on the `Fork` button. + +Then, from your fork's page, copy the `Git Read-Only` URL to your clipboard. +You MUST perform the following commands in the folder you choose, replacing +`$URL` by the URL you just copied, `$UPSTREAM_URL` by the `Git Read-Only` +project of the official repository, and `$PROJECT` by the name of this project. + +``` bash +$ git clone "$URL" +$ cd $PROJECT +$ git remote add upstream $UPSTREAM_URL +``` + +Branching +--------- + +Before starting working on the code, you MUST update to `upstream`. The +project is always evolving, and as such you SHOULD always strive to keep +up to date when submitting patches to make sure they can be merged without +conflicts. + +To update the current branch to `upstream`, you can use the following commands. + +``` bash +$ git fetch upstream +$ git rebase upstream/master +``` + +It may ask you to stash your changes, in which case you stash with: + +``` bash +$ git stash +``` + +And put your changes back in with: + +``` bash +$ git stash pop +``` + +You SHOULD use these commands both before working on your patch and before +submitting the pull request. If conflicts arise it is your responsability +to deal with them. + +You MUST create a new branch for your work. First make sure you have +'fetched' `master` + +``` bash +$ git checkout -b $BRANCH upstream/master +``` + +You MUST use a an insightful branch name. + +If you later need to switch back to an existing branch `$BRANCH`, you can use: + +``` bash +$ git checkout $BRANCH +``` + +Source editing +-------------- + +The following rules MUST be followed: + * Indentation uses 4 horizontal spaces + * Tabs should not be used + * Do NOT align code; only indentation is allowed + + +The following rules SHOULD be followed: + * Write small functions whenever possible + * Avoid having too many clauses containing clauses containing clauses + * Lines SHOULD NOT span more than 80 columns + +When in doubt indentation as performed in the Erlang Emacs Mode is +correct. + +Committing +---------- + +You MUST ensure that all commits pass all tests and do not have extra +Dialyzer warnings. + +You MUST put all the related work in a single commit. Fixing a bug is one +commit, adding a feature is one commit, adding two features is two commits. + +You MUST write a proper commit title and message. The commit title MUST be +at most 72 characters; it is the first line of the commit text. The second +line of the commit text MUST be left blank. The third line and beyond is the +commit message. You SHOULD write a commit message. If you do, you MUST make +all lines smaller than 80 characters. You SHOULD explain what the commit +does, what references you used and any other information that helps +understanding your work. + +Submitting the pull request +--------------------------- + +You MUST push your branch `$BRANCH` to GitHub, using the following command: + +``` bash +$ git push origin $BRANCH +``` + +You MUST then submit the pull request by using the GitHub interface to +the `master` branch. You SHOULD provide an explanatory message and refer +to any previous ticket related to this patch. From 38141c5c24e89d72253a5fc9824887f2735fd822 Mon Sep 17 00:00:00 2001 From: Seth Falcon Date: Mon, 22 Apr 2013 12:44:59 -0700 Subject: [PATCH 074/240] Fix typo in typer target in Makefile The typer target now works. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 51727d2..714d70e 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ $(ERLWARE_COMMONS_PLT).$(ERL_VER): $(ERLWARE_COMMONS_PLT).$(ERL_VER).base dialyzer: $(ERLWARE_COMMONS_PLT).$(ERL_VER) dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -Wrace_conditions -r ./ebin -typer: $(ERLWARE_COMMONS_PLT).$(ERL)VER( +typer: $(ERLWARE_COMMONS_PLT).$(ERL_VER) typer --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -r ./src shell: compile From 38cd7a4d62fdc8952f85e6d24a14f61b395a48b2 Mon Sep 17 00:00:00 2001 From: Seth Falcon Date: Mon, 22 Apr 2013 12:57:09 -0700 Subject: [PATCH 075/240] Use deps directory to trigger get-deps A `make distclean` now removes the deps directory and all of its contents. The default target now looks for the presence of the deps directory to determine if `rebar get-deps compile` should be run. The main benefit being that one can now do: `make distclean && make` without a call to `make get-deps`. The get-deps target is left in place for convenince and back compat. The get-deps target was updated slightly to run get-deps and compile as part of a single command. This should be slightly more efficient. --- Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 714d70e..0871acf 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,13 @@ ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt all: compile doc test #dialyzer #fail on travis -get-deps: - $(REBAR) get-deps - $(REBAR) compile +deps: + $(REBAR) get-deps compile -compile: +get-deps: + $(REBAR) get-deps compile + +compile: deps $(REBAR) skip_deps=true compile doc: compile @@ -81,6 +83,6 @@ clean: distclean: clean rm -rf $(ERLWARE_COMMONS_PLT).$(ERL_VER) - rm -rvf $(CURDIR)/deps/* + rm -rvf $(CURDIR)/deps rebuild: distclean get-deps all From d9c6ec1d28387207a65d03a6dcce6367283117ea Mon Sep 17 00:00:00 2001 From: Seth Falcon Date: Mon, 22 Apr 2013 14:48:08 -0700 Subject: [PATCH 076/240] Make proper and neotoma dev-only dependencies This patch makes erlware_commons easier to include as a dependency by removing depedencies that are not needed at run time. The top-level Makefile creates a .DEV_MODE marker file which is detected by rebar.config.script. When the marker file is present, the development only dependencies proper and neotoma are included and a macro 'DEV_ONLY' is defined. The macro is used to only enable the proper tests for development mode. The ec_semver_parser.peg is now located in priv/ and is moved into src/ by the Makefile. The generated ec_semver_parser.erl is now under version control; it need not be rebuilt by all projects wishing to include erlware_commons. It will be rebuilt, as before this change, on every make invocation. --- .gitignore | 3 +- Makefile | 8 +- {src => priv}/ec_semver_parser.peg | 0 rebar.config | 8 +- rebar.config.script | 53 +++++-- src/ec_semver_parser.erl | 231 +++++++++++++++++++++++++++++ test/ec_dictionary_proper.erl | 3 + 7 files changed, 286 insertions(+), 20 deletions(-) rename {src => priv}/ec_semver_parser.peg (100%) create mode 100644 src/ec_semver_parser.erl diff --git a/.gitignore b/.gitignore index 443f45b..0489cab 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ ebin/* _build erl_crash.dump *.pyc -src/ec_semver_parser.erl + +src/ec_semver_parser.peg diff --git a/Makefile b/Makefile index 0871acf..031bba4 100644 --- a/Makefile +++ b/Makefile @@ -19,15 +19,20 @@ ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt all: compile doc test #dialyzer #fail on travis -deps: +deps: .DEV_MODE $(REBAR) get-deps compile +.DEV_MODE: + touch $@ + cp priv/ec_semver_parser.peg src + get-deps: $(REBAR) get-deps compile compile: deps $(REBAR) skip_deps=true compile + doc: compile - $(REBAR) skip_deps=true doc @@ -84,5 +89,6 @@ clean: distclean: clean rm -rf $(ERLWARE_COMMONS_PLT).$(ERL_VER) rm -rvf $(CURDIR)/deps + rm -rvf .DEV_MODE rebuild: distclean get-deps all diff --git a/src/ec_semver_parser.peg b/priv/ec_semver_parser.peg similarity index 100% rename from src/ec_semver_parser.peg rename to priv/ec_semver_parser.peg diff --git a/rebar.config b/rebar.config index 57dc49a..6bc7d6f 100644 --- a/rebar.config +++ b/rebar.config @@ -1,11 +1,9 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- %% Dependencies ================================================================ -{deps, [{neotoma, "", - {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, - {proper, "", {git, "https://github.com/bkearns/proper.git", {branch, master}}}, - {rebar_vsn_plugin, ".*", {git, "https://github.com/erlware/rebar_vsn_plugin.git", - {branch, "master"}}}]}. +{deps, [{rebar_vsn_plugin, ".*", + {git, "https://github.com/erlware/rebar_vsn_plugin.git", + {branch, "master"}}}]}. {erl_first_files, ["ec_dictionary"]}. diff --git a/rebar.config.script b/rebar.config.script index c19a751..bbe043f 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -1,15 +1,42 @@ +%% Merge the list values in `ToAdd' into the list found at key `Key' +%% in proplist `C'. Don't duplicate items. New Items are added to the +%% front of existing items. It is an error if the value at `Key' is +%% not a list in `C'. +MergeConfig = fun({Key, ToAdd}, C) -> + case lists:keyfind(Key, 1, C) of + false -> + lists:keystore(Key, 1, C, {Key, ToAdd}); + {Key, List} when is_list(List) -> + %% remove items in ToAdd already in List + ToAdd1 = [ I || I <- ToAdd, not lists:member(I, List) ], + lists:keystore(Key, 1, C, {Key, ToAdd1 ++ List }) + end + end. + {match, [ErtsNumber]} = re:run(erlang:system_info(otp_release), "R(\\d+).+", [{capture, [1], list}]), ErtsVsn = erlang:list_to_integer(ErtsNumber), -Opts1 = case lists:keysearch(erl_opts, 1, CONFIG) of - {value, {erl_opts, Opts0}} -> - Opts0; - false -> - [] - end, -Opts2 = if - ErtsVsn >= 15 -> - [{d, have_callback_support} | Opts1]; - true -> - Opts1 - end, -lists:keystore(erl_opts, 1, CONFIG, {erl_opts, Opts2}). +AddErlOpts = if + ErtsVsn >= 15 -> + [{d, have_callback_support}]; + true -> + [] + end, + +DevOnlyDeps = [{neotoma, "", + {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, + {proper, "", + {git, "https://github.com/bkearns/proper.git", {branch, master}}}], + +Config1 = MergeConfig({erl_opts, AddErlOpts}, CONFIG), + +ConfigPath = filename:dirname(SCRIPT), +DevMarker = filename:join([ConfigPath, ".DEV_MODE"]), +case filelib:is_file(DevMarker) of + true -> + lists:foldl(MergeConfig, Config1, + [{deps, DevOnlyDeps}, + {erl_opts, [{d, 'DEV_ONLY'}]}]); + false -> + Config1 +end. + diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl new file mode 100644 index 0000000..3829c71 --- /dev/null +++ b/src/ec_semver_parser.erl @@ -0,0 +1,231 @@ +-module(ec_semver_parser). +-export([parse/1,file/1]). +-compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). + + +-compile(export_all). +-spec file(file:name()) -> any(). +file(Filename) -> {ok, Bin} = file:read_file(Filename), parse(Bin). + +-spec parse(binary() | list()) -> any(). +parse(List) when is_list(List) -> parse(list_to_binary(List)); +parse(Input) when is_binary(Input) -> + setup_memo(), + Result = case 'semver'(Input,{{line,1},{column,1}}) of + {AST, <<>>, _Index} -> AST; + Any -> Any + end, + release_memo(), Result. + +'semver'(Input, Index) -> + p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). + +'major_minor_patch_min_patch'(Input, Index) -> + p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end). + +'version_part'(Input, Index) -> + p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end). + +'numeric_part'(Input, Index) -> + p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). + +'alpha_part'(Input, Index) -> + p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). + + +transform(_,Node,_Index) -> Node. + +p(Inp, Index, Name, ParseFun) -> + p(Inp, Index, Name, ParseFun, fun(N, _Idx) -> N end). + +p(Inp, StartIndex, Name, ParseFun, TransformFun) -> + case get_memo(StartIndex, Name) of % See if the current reduction is memoized + {ok, Memo} -> %Memo; % If it is, return the stored result + Memo; + _ -> % If not, attempt to parse + Result = case ParseFun(Inp, StartIndex) of + {fail,_} = Failure -> % If it fails, memoize the failure + Failure; + {Match, InpRem, NewIndex} -> % If it passes, transform and memoize the result. + Transformed = TransformFun(Match, StartIndex), + {Transformed, InpRem, NewIndex} + end, + memoize(StartIndex, Name, Result), + Result + end. + +setup_memo() -> + put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])). + +release_memo() -> + ets:delete(memo_table_name()). + +memoize(Index, Name, Result) -> + Memo = case ets:lookup(memo_table_name(), Index) of + [] -> []; + [{Index, Plist}] -> Plist + end, + ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}). + +get_memo(Index, Name) -> + case ets:lookup(memo_table_name(), Index) of + [] -> {error, not_found}; + [{Index, Plist}] -> + case proplists:lookup(Name, Plist) of + {Name, Result} -> {ok, Result}; + _ -> {error, not_found} + end + end. + +memo_table_name() -> + get({parse_memo_table, ?MODULE}). + +p_eof() -> + fun(<<>>, Index) -> {eof, [], Index}; + (_, Index) -> {fail, {expected, eof, Index}} end. + +p_optional(P) -> + fun(Input, Index) -> + case P(Input, Index) of + {fail,_} -> {[], Input, Index}; + {_, _, _} = Success -> Success + end + end. + +p_not(P) -> + fun(Input, Index)-> + case P(Input,Index) of + {fail,_} -> + {[], Input, Index}; + {Result, _, _} -> {fail, {expected, {no_match, Result},Index}} + end + end. + +p_assert(P) -> + fun(Input,Index) -> + case P(Input,Index) of + {fail,_} = Failure-> Failure; + _ -> {[], Input, Index} + end + end. + +p_and(P) -> + p_seq(P). + +p_seq(P) -> + fun(Input, Index) -> + p_all(P, Input, Index, []) + end. + +p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index}; +p_all([P|Parsers], Inp, Index, Accum) -> + case P(Inp, Index) of + {fail, _} = Failure -> Failure; + {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum]) + end. + +p_choose(Parsers) -> + fun(Input, Index) -> + p_attempt(Parsers, Input, Index, none) + end. + +p_attempt([], _Input, _Index, Failure) -> Failure; +p_attempt([P|Parsers], Input, Index, FirstFailure)-> + case P(Input, Index) of + {fail, _} = Failure -> + case FirstFailure of + none -> p_attempt(Parsers, Input, Index, Failure); + _ -> p_attempt(Parsers, Input, Index, FirstFailure) + end; + Result -> Result + end. + +p_zero_or_more(P) -> + fun(Input, Index) -> + p_scan(P, Input, Index, []) + end. + +p_one_or_more(P) -> + fun(Input, Index)-> + Result = p_scan(P, Input, Index, []), + case Result of + {[_|_], _, _} -> + Result; + _ -> + {fail, {expected, Failure, _}} = P(Input,Index), + {fail, {expected, {at_least_one, Failure}, Index}} + end + end. + +p_label(Tag, P) -> + fun(Input, Index) -> + case P(Input, Index) of + {fail,_} = Failure -> + Failure; + {Result, InpRem, NewIndex} -> + {{Tag, Result}, InpRem, NewIndex} + end + end. + +p_scan(_, [], Index, Accum) -> {lists:reverse( Accum ), [], Index}; +p_scan(P, Inp, Index, Accum) -> + case P(Inp, Index) of + {fail,_} -> {lists:reverse(Accum), Inp, Index}; + {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum]) + end. + +p_string(S) when is_list(S) -> p_string(list_to_binary(S)); +p_string(S) -> + Length = erlang:byte_size(S), + fun(Input, Index) -> + try + <> = Input, + {S, Rest, p_advance_index(S, Index)} + catch + error:{badmatch,_} -> {fail, {expected, {string, S}, Index}} + end + end. + +p_anything() -> + fun(<<>>, Index) -> {fail, {expected, any_character, Index}}; + (Input, Index) when is_binary(Input) -> + <> = Input, + {<>, Rest, p_advance_index(<>, Index)} + end. + +p_charclass(Class) -> + {ok, RE} = re:compile(Class, [unicode, dotall]), + fun(Inp, Index) -> + case re:run(Inp, RE, [anchored]) of + {match, [{0, Length}|_]} -> + {Head, Tail} = erlang:split_binary(Inp, Length), + {Head, Tail, p_advance_index(Head, Index)}; + _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}} + end + end. + +p_regexp(Regexp) -> + {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]), + fun(Inp, Index) -> + case re:run(Inp, RE) of + {match, [{0, Length}|_]} -> + {Head, Tail} = erlang:split_binary(Inp, Length), + {Head, Tail, p_advance_index(Head, Index)}; + _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}} + end + end. + +line({{line,L},_}) -> L; +line(_) -> undefined. + +column({_,{column,C}}) -> C; +column(_) -> undefined. + +p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings + lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput)); +p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters + {{line, Line}, {column, Col}} = Index, + case MatchedInput of + $\n -> {{line, Line+1}, {column, 1}}; + _ -> {{line, Line}, {column, Col+1}} + end. diff --git a/test/ec_dictionary_proper.erl b/test/ec_dictionary_proper.erl index d30f542..a455e90 100644 --- a/test/ec_dictionary_proper.erl +++ b/test/ec_dictionary_proper.erl @@ -5,6 +5,8 @@ %% proper:module(ec_dictionary_proper). -module(ec_dictionary_proper). +-ifdef(DEV_ONLY). + -export([my_dict/0, dict/1, sym_dict/0, sym_dict/1, gb_tree/0, gb_tree/1, sym_dict2/0]). -include_lib("proper/include/proper.hrl"). @@ -221,3 +223,4 @@ gb_tree(0) -> gb_tree(N) -> gb_trees:enter(key(),value(),gb_tree(N-1)). +-endif. From e984618c3e940feb5953fc2c6f61a3d61dd1a5dd Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Tue, 23 Apr 2013 17:07:52 -0500 Subject: [PATCH 077/240] Fix Formatting AM/PM for 12PM ({Date,{12,0,0}}) --- src/ec_date.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 66ffaeb..bda94c2 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -453,11 +453,11 @@ format([$z|T], {Date,_}=Dt, Acc) -> format(T, Dt, [itol(days_in_year(Date))|Acc]); %% Time Formats -format([$a|T], Dt={_,{H,_,_}}, Acc) when H > 12 -> +format([$a|T], Dt={_,{H,_,_}}, Acc) when H >= 12 -> format(T, Dt, ["pm"|Acc]); format([$a|T], Dt={_,{_,_,_}}, Acc) -> format(T, Dt, ["am"|Acc]); -format([$A|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> +format([$A|T], {_,{H,_,_}}=Dt, Acc) when H >= 12 -> format(T, Dt, ["PM"|Acc]); format([$A|T], Dt={_,{_,_,_}}, Acc) -> format(T, Dt, ["AM"|Acc]); @@ -680,6 +680,8 @@ ltoi(X) -> -define(DATE, {{2001,3,10},{17,16,17}}). -define(DATEMS, {{2001,3,10},{17,16,17,123456}}). +-define(DATE_NOON, {{2001,3,10},{12,0,0}}). +-define(DATE_MIDNIGHT, {{2001,3,10},{0,0,0}}). -define(ISO, "o \\WW"). basic_format_test_() -> @@ -696,6 +698,10 @@ basic_format_test_() -> ?_assertEqual(format("H:i:s",?DATE), "17:16:17"), ?_assertEqual(format("z",?DATE), "68"), ?_assertEqual(format("D M j G:i:s Y",?DATE), "Sat Mar 10 17:16:17 2001"), + ?_assertEqual(format("ga",?DATE_NOON), "12pm"), + ?_assertEqual(format("gA",?DATE_NOON), "12PM"), + ?_assertEqual(format("ga",?DATE_MIDNIGHT), "12am"), + ?_assertEqual(format("gA",?DATE_MIDNIGHT), "12AM"), ?_assertEqual(format("h-i-s, j-m-y, it is w Day",?DATE), "05-16-17, 10-03-01, 1631 1617 6 Satpm01"), From 652fcc1e2334b1a44291837ce48784d2803b8dbb Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Wed, 24 Apr 2013 09:53:42 -0700 Subject: [PATCH 078/240] remove ec_file:consult/1 as it provides very little value Fixes #1 --- src/ec_file.erl | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index c291a81..1a24560 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -22,8 +22,7 @@ md5sum/1, read/1, write/2, - write_term/2, - consult/1 + write_term/2 ]). -export_type([ @@ -174,16 +173,6 @@ mkdir_path(Path) -> mkdir_p(Path). -%% @doc consult an erlang term file from the file system. -%% Provide user readible exeption on failure. --spec consult(FilePath::file:name()) -> term(). -consult(FilePath) -> - case file:consult(FilePath) of - {ok, [Term]} -> - Term; - Error -> - Error - end. %% @doc read a file from the file system. Provide UEX exeption on failure. -spec read(FilePath::file:filename()) -> binary() | {error, Reason::term()}. read(FilePath) -> @@ -327,12 +316,10 @@ file_test() -> filelib:ensure_dir(TermFile), filelib:ensure_dir(TermFileCopy), write_term(TermFile, "term"), - ?assertMatch("term", consult(TermFile)), ?assertMatch({ok, <<"\"term\". ">>}, read(TermFile)), copy(filename:dirname(TermFile), filename:dirname(TermFileCopy), - [recursive]), - ?assertMatch("term", consult(TermFileCopy)). + [recursive]). teardown_test() -> Dir = insecure_mkdtemp(), From 8870c422caa4a4f5ea789dab3e417c615b0a68c6 Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Wed, 24 Apr 2013 09:53:30 -0700 Subject: [PATCH 079/240] minor updates from a new version of neotoma --- src/ec_semver_parser.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl index 3829c71..1e90dd3 100644 --- a/src/ec_semver_parser.erl +++ b/src/ec_semver_parser.erl @@ -18,19 +18,19 @@ parse(Input) when is_binary(Input) -> release_memo(), Result. 'semver'(Input, Index) -> - p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). + p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). 'major_minor_patch_min_patch'(Input, Index) -> - p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end). + p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) -> transform('major_minor_patch_min_patch', Node, Idx) end). 'version_part'(Input, Index) -> - p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end). + p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) -> transform('version_part', Node, Idx) end). 'numeric_part'(Input, Index) -> - p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). + p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) -> erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). 'alpha_part'(Input, Index) -> - p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). + p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) -> erlang:iolist_to_binary(Node) end). transform(_,Node,_Index) -> Node. From 7e2c37e2f5f1e61067f61c7ce0743c1c33282b0f Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Wed, 24 Apr 2013 09:54:10 -0700 Subject: [PATCH 080/240] fix bug in rebuild introduced by new makefile changes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 031bba4..05c17ca 100644 --- a/Makefile +++ b/Makefile @@ -91,4 +91,4 @@ distclean: clean rm -rvf $(CURDIR)/deps rm -rvf .DEV_MODE -rebuild: distclean get-deps all +rebuild: distclean all From 417a4c32293a7d3b309ec41e4814315221fb10df Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Wed, 24 Apr 2013 09:54:22 -0700 Subject: [PATCH 081/240] minor enhancements and cleanup to the makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 05c17ca..e05f06a 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,9 @@ endif ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt -.PHONY: all compile doc clean test shell distclean pdf get-deps rebuild #dialyzer typer #fail on Travis. +.PHONY: all compile doc clean test shell distclean pdf get-deps rebuild dialyzer typer -all: compile doc test #dialyzer #fail on travis +all: compile doc test deps: .DEV_MODE $(REBAR) get-deps compile @@ -50,13 +50,13 @@ $(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel:$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ - --apps kernel + --apps kernel $(ERLWARE_COMMONS_PLT).$(ERL_VER).base:$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ - --apps stdlib + --apps stdlib $(ERLWARE_COMMONS_PLT).$(ERL_VER): $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER) From 8bc27f62fd240a89a616edec0765570bfa6562ef Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Fri, 30 Aug 2013 06:52:20 -0500 Subject: [PATCH 082/240] Add vi modelines to files. Ignore vim backup files --- .gitignore | 1 + src/ec_assoc_list.erl | 1 + src/ec_date.erl | 1 + src/ec_dict.erl | 1 + src/ec_dictionary.erl | 1 + src/ec_file.erl | 1 + src/ec_gb_trees.erl | 1 + src/ec_lists.erl | 1 + src/ec_orddict.erl | 1 + src/ec_plists.erl | 1 + src/ec_rbdict.erl | 1 + src/ec_semver.erl | 1 + src/ec_semver_parser.erl | 1 + src/ec_talk.erl | 1 + 14 files changed, 14 insertions(+) diff --git a/.gitignore b/.gitignore index 0489cab..929000d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,6 @@ ebin/* _build erl_crash.dump *.pyc +*~ src/ec_semver_parser.peg diff --git a/src/ec_assoc_list.erl b/src/ec_assoc_list.erl index e9bd0cc..9921f55 100644 --- a/src/ec_assoc_list.erl +++ b/src/ec_assoc_list.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @author Eric Merritt %%% @copyright 2011 Erlware, LLC. diff --git a/src/ec_date.erl b/src/ec_date.erl index bda94c2..55b6b93 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -1,3 +1,4 @@ +%% vi:ts=4 sw=4 et %% @copyright Dale Harvey %% @doc Format dates in erlang %% diff --git a/src/ec_dict.erl b/src/ec_dict.erl index 1c5d319..49f3d96 100644 --- a/src/ec_dict.erl +++ b/src/ec_dict.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @author Eric Merritt %%% @copyright 2011 Erlware, LLC. diff --git a/src/ec_dictionary.erl b/src/ec_dictionary.erl index 416df72..423914a 100644 --- a/src/ec_dictionary.erl +++ b/src/ec_dictionary.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @author Eric Merritt %%% @copyright 2011 Erlware, LLC. diff --git a/src/ec_file.erl b/src/ec_file.erl index 1a24560..92430cd 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @copyright (C) 2011, Erlware LLC %%% @doc diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl index 7427740..811cd1b 100644 --- a/src/ec_gb_trees.erl +++ b/src/ec_gb_trees.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @author Eric Merritt %%% @copyright 2011 Erlware, LLC. diff --git a/src/ec_lists.erl b/src/ec_lists.erl index cbc1f0b..689813e 100644 --- a/src/ec_lists.erl +++ b/src/ec_lists.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @copyright (C) 2011, Erlware LLC %%% @doc diff --git a/src/ec_orddict.erl b/src/ec_orddict.erl index fdd8a38..90418f5 100644 --- a/src/ec_orddict.erl +++ b/src/ec_orddict.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @author Eric Merritt %%% @copyright 2011 Erlware, LLC. diff --git a/src/ec_plists.erl b/src/ec_plists.erl index a021d02..7512fdc 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -1,4 +1,5 @@ %%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%%% vi:ts=4 sw=4 et %%% The MIT License %%% %%% Copyright (c) 2007 Stephen Marsh diff --git a/src/ec_rbdict.erl b/src/ec_rbdict.erl index f28f625..60e337f 100644 --- a/src/ec_rbdict.erl +++ b/src/ec_rbdict.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%% Copyright (c) 2008 Robert Virding. All rights reserved. %%% %%% Redistribution and use in source and binary forms, with or without diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 5855c23..bf4e157 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et %%%------------------------------------------------------------------- %%% @copyright (C) 2011, Erlware LLC %%% @doc diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl index 1e90dd3..ba68238 100644 --- a/src/ec_semver_parser.erl +++ b/src/ec_semver_parser.erl @@ -1,3 +1,4 @@ +%%% vi:ts=4 sw=4 et -module(ec_semver_parser). -export([parse/1,file/1]). -compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). diff --git a/src/ec_talk.erl b/src/ec_talk.erl index 4a82d1b..936f9ed 100644 --- a/src/ec_talk.erl +++ b/src/ec_talk.erl @@ -1,4 +1,5 @@ %% -*- mode: Erlang; fill-column: 79; comment-column: 70; -*- +%% vi:ts=4 sw=4 et %%%--------------------------------------------------------------------------- %%% Permission is hereby granted, free of charge, to any person %%% obtaining a copy of this software and associated documentation From 79c5436c859933ce1e23b73d955e01213950dac0 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 09:26:47 -0700 Subject: [PATCH 083/240] add utility type conversions to erlware commons --- src/ec_cnv.erl | 309 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 src/ec_cnv.erl diff --git a/src/ec_cnv.erl b/src/ec_cnv.erl new file mode 100644 index 0000000..a063e2a --- /dev/null +++ b/src/ec_cnv.erl @@ -0,0 +1,309 @@ +%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright (C) 2012 Erlware, LLC. +%%% +-module(ec_cnv). + +%% API +-export([to_integer/1, + to_integer/2, + to_float/1, + to_float/2, + to_number/1, + to_list/1, + to_binary/1, + to_atom/1, + to_boolean/1, + is_true/1, + is_false/1]). + +-ifndef(NOTEST). +-include_lib("proper/include/proper.hrl"). +-endif. + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc +%% Automatic conversion of a term into integer type. The conversion +%% will round a float value if nonstrict is specified otherwise badarg +-spec to_integer(string() | binary() | integer() | float()) -> + integer(). +to_integer(X)-> + to_integer(X, nonstrict). + +-spec to_integer(string() | binary() | integer() | float(), + strict | nonstrict) -> + integer(). +to_integer(X, strict) + when erlang:is_float(X) -> + erlang:error(badarg); +to_integer(X, nonstrict) + when erlang:is_float(X) -> + erlang:round(X); +to_integer(X, S) + when erlang:is_binary(X) -> + to_integer(erlang:binary_to_list(X), S); +to_integer(X, S) + when erlang:is_list(X) -> + try erlang:list_to_integer(X) of + Result -> + Result + catch + error:badarg when S =:= nonstrict -> + erlang:round(erlang:list_to_float(X)) + end; +to_integer(X, _) + when erlang:is_integer(X) -> + X. + +%% @doc +%% Automatic conversion of a term into float type. badarg if strict +%% is defined and an integer value is passed. +-spec to_float(string() | binary() | integer() | float()) -> + float(). +to_float(X) -> + to_float(X, nonstrict). + +-spec to_float(string() | binary() | integer() | float(), + strict | nonstrict) -> + float(). +to_float(X, S) when is_binary(X) -> + to_float(erlang:binary_to_list(X), S); +to_float(X, S) + when erlang:is_list(X) -> + try erlang:list_to_float(X) of + Result -> + Result + catch + error:badarg when S =:= nonstrict -> + erlang:list_to_integer(X) * 1.0 + end; +to_float(X, strict) when + erlang:is_integer(X) -> + erlang:error(badarg); +to_float(X, nonstrict) + when erlang:is_integer(X) -> + X * 1.0; +to_float(X, _) when erlang:is_float(X) -> + X. + +%% @doc +%% Automatic conversion of a term into number type. +-spec to_number(binary() | string() | number()) -> + number(). +to_number(X) + when erlang:is_number(X) -> + X; +to_number(X) + when erlang:is_binary(X) -> + to_number(to_list(X)); +to_number(X) + when erlang:is_list(X) -> + try list_to_integer(X) of + Int -> Int + catch + error:badarg -> + list_to_float(X) + end. + +%% @doc +%% Automatic conversion of a term into Erlang list +-spec to_list(atom() | list() | binary() | integer() | float()) -> + list(). +to_list(X) + when erlang:is_float(X) -> + erlang:float_to_list(X); +to_list(X) + when erlang:is_integer(X) -> + erlang:integer_to_list(X); +to_list(X) + when erlang:is_binary(X) -> + erlang:binary_to_list(X); +to_list(X) + when erlang:is_atom(X) -> + erlang:atom_to_list(X); +to_list(X) + when erlang:is_list(X) -> + X. + +%% @doc +%% Known limitations: +%% Converting [256 | _], lists with integers > 255 +-spec to_binary(atom() | string() | binary() | integer() | float()) -> + binary(). +to_binary(X) + when erlang:is_float(X) -> + to_binary(to_list(X)); +to_binary(X) + when erlang:is_integer(X) -> + erlang:iolist_to_binary(integer_to_list(X)); +to_binary(X) + when erlang:is_atom(X) -> + erlang:list_to_binary(erlang:atom_to_list(X)); +to_binary(X) + when erlang:is_list(X) -> + erlang:iolist_to_binary(X); +to_binary(X) + when erlang:is_binary(X) -> + X. + +-spec to_boolean(binary() | string() | atom()) -> + boolean(). +to_boolean(<<"true">>) -> + true; +to_boolean("true") -> + true; +to_boolean(true) -> + true; +to_boolean(<<"false">>) -> + false; +to_boolean("false") -> + false; +to_boolean(false) -> + false. + +-spec is_true(binary() | string() | atom()) -> + boolean(). +is_true(<<"true">>) -> + true; +is_true("true") -> + true; +is_true(true) -> + true; +is_true(_) -> + false. + +-spec is_false(binary() | string() | atom()) -> + boolean(). +is_false(<<"false">>) -> + true; +is_false("false") -> + true; +is_false(false) -> + true; +is_false(_) -> + false. + +%% @doc +%% Automation conversion a term to an existing atom. badarg is +%% returned if the atom doesn't exist. the safer version, won't let +%% you leak atoms +-spec to_atom(atom() | list() | binary() | integer() | float()) -> + atom(). +to_atom(X) + when erlang:is_atom(X) -> + X; +to_atom(X) + when erlang:is_list(X) -> + erlang:list_to_existing_atom(X); +to_atom(X) -> + to_atom(to_list(X)). + +%%%=================================================================== +%%% API +%%%=================================================================== + +-ifndef(NOTEST). +-include_lib("eunit/include/eunit.hrl"). + +force_proper_test_() -> + {"Runs PropEr test during EUnit phase", + {timeout, 15000, [?_assertEqual([], proper:module(?MODULE))]}}. + +to_integer_test() -> + ?assertError(badarg, to_integer(1.5, strict)). + +to_float_test() -> + ?assertError(badarg, to_float(10, strict)). + +to_atom_test() -> + ?assertMatch(true, to_atom("true")), + ?assertMatch(true, to_atom(<<"true">>)), + ?assertMatch(false, to_atom(<<"false">>)), + ?assertMatch(false, to_atom(false)), + ?assertError(badarg, to_atom("hello_foo_bar_baz")), + + S = erlang:list_to_atom("1"), + ?assertMatch(S, to_atom(1)). + +to_boolean_test()-> + ?assertMatch(true, to_boolean(<<"true">>)), + ?assertMatch(true, to_boolean("true")), + ?assertMatch(true, to_boolean(true)), + ?assertMatch(false, to_boolean(<<"false">>)), + ?assertMatch(false, to_boolean("false")), + ?assertMatch(false, to_boolean(false)). + +%%% PropEr testing + +prop_to_integer() -> + ?FORALL({F, I}, {float(), integer()}, + begin + Is = [[Fun(N), N] || + Fun <- [fun to_list/1, + fun to_binary/1], + N <- [F, I]], + lists:all(fun([FN, N]) -> + erlang:is_integer(to_integer(N)) andalso + erlang:is_integer(to_integer(FN)) + end, Is) + end). + +prop_to_list() -> + ?FORALL({A, L, B, I, F}, {atom(), list(), binary(), integer(), float()}, + lists:all(fun(X) -> + erlang:is_list(to_list(X)) + end, [A, L, B, I, F])). + +prop_to_binary() -> + ?FORALL({A, L, B, I, F, IO}, {atom(), list(range(0,255)), binary(), + integer(), float(), iolist()}, + lists:all(fun(X) -> + erlang:is_binary(to_binary(X)) + end, [A, L, B, I, F, IO])). + +prop_iolist_t() -> + ?FORALL(IO, iolist(), erlang:is_binary(to_binary(IO))). + +prop_to_float() -> + ?FORALL({F, I}, {float(), integer()}, + begin + Fs = [[Fun(N), N] || + Fun <- [fun to_list/1, fun to_binary/1], + N <- [F, I]], + lists:all(fun([FN, N]) -> + erlang:is_float(to_float(N)) andalso + erlang:is_float(to_float(FN)) + end, Fs) + end). + +prop_to_number() -> + ?FORALL({F, I}, {float(), integer()}, + begin + Is = [[Fun(N), N] || + Fun <- [fun to_list/1, fun to_binary/1], + N <- [F, I] ], + lists:all(fun([FN, N]) -> + erlang:is_number(to_number(N)) andalso + erlang:is_number(to_number(FN)) + end, Is) + end). +-endif. From 558185b9b965c6b194beeda26110bddc7b59aaab Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Sun, 13 Oct 2013 22:34:14 -0500 Subject: [PATCH 084/240] add a command line programming module to the system This is a general module that helps output from command line applications written in erlang. --- include/ec_cmd_log.hrl | 24 ++++ src/ec_cmd_log.erl | 255 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 include/ec_cmd_log.hrl create mode 100644 src/ec_cmd_log.erl diff --git a/include/ec_cmd_log.hrl b/include/ec_cmd_log.hrl new file mode 100644 index 0000000..170d399 --- /dev/null +++ b/include/ec_cmd_log.hrl @@ -0,0 +1,24 @@ +%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright (C) 2012 Erlware, LLC. + +-define(EC_ERROR, 0). +-define(EC_WARN, 1). +-define(EC_INFO, 2). +-define(EC_DEBUG, 3). diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl new file mode 100644 index 0000000..0be4143 --- /dev/null +++ b/src/ec_cmd_log.erl @@ -0,0 +1,255 @@ +%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright (C) 2012 Erlware, LLC. +%%% +%%% @doc This provides simple output functions for command line apps. You should +%%% use this to talk to the users if you are wrting code for the system +-module(ec_cmd_log). + +-export([new/1, + new/2, + log/4, + should/2, + debug/2, + debug/3, + info/2, + info/3, + error/2, + error/3, + warn/2, + warn/3, + log_level/1, + atom_log_level/1, + format/1]). + +-include_lib("erlware_commons/include/ec_cmd_log.hrl"). + +-define(RED, 31). +-define(GREEN, 32). +-define(YELLOW, 33). +-define(BLUE, 34). +-define(MAGENTA, 35). +-define(CYAN, 36). + +-define(PREFIX, "===> "). + +-record(state_t, {mod=?MODULE :: ec_log, + log_level=0 :: int_log_level(), + caller=api :: api | command_line}). + +%%============================================================================ +%% types +%%============================================================================ +-export_type([t/0, + int_log_level/0, + atom_log_level/0, + log_level/0, + log_fun/0]). + +-type log_level() :: int_log_level() | atom_log_level(). + +-type int_log_level() :: 0..3. + +-type atom_log_level() :: error | warn | info | debug. + +-type log_fun() :: fun(() -> iolist()). + +-type color() :: 31..36. + +-opaque t() :: record(state_t). + +%%============================================================================ +%% API +%%============================================================================ +%% @doc Create a new 'log level' for the system +-spec new(log_level()) -> t(). +new(LogLevel) -> + new(LogLevel, api). + +new(LogLevel, Caller) when LogLevel >= 0, LogLevel =< 3 -> + #state_t{mod=?MODULE, log_level=LogLevel, caller=Caller}; +new(AtomLogLevel, Caller) + when AtomLogLevel =:= error; + AtomLogLevel =:= warn; + AtomLogLevel =:= info; + AtomLogLevel =:= debug -> + LogLevel = case AtomLogLevel of + error -> 0; + warn -> 1; + info -> 2; + debug -> 3 + end, + new(LogLevel, Caller). + +%% @doc log at the debug level given the current log state with a string or +%% function that returns a string +-spec debug(t(), string() | log_fun()) -> ok. +debug(LogState, Fun) + when erlang:is_function(Fun) -> + log(LogState, ?EC_DEBUG, fun() -> + colorize(LogState, ?CYAN, false, Fun()) + end); +debug(LogState, String) -> + debug(LogState, "~s~n", [String]). + +%% @doc log at the debug level given the current log state with a format string +%% and argements @see io:format/2 +-spec debug(t(), string(), [any()]) -> ok. +debug(LogState, FormatString, Args) -> + log(LogState, ?EC_DEBUG, colorize(LogState, ?CYAN, false, FormatString), Args). + +%% @doc log at the info level given the current log state with a string or +%% function that returns a string +-spec info(t(), string() | log_fun()) -> ok. +info(LogState, Fun) + when erlang:is_function(Fun) -> + log(LogState, ?EC_INFO, fun() -> + colorize(LogState, ?GREEN, false, Fun()) + end); +info(LogState, String) -> + info(LogState, "~s~n", [String]). + +%% @doc log at the info level given the current log state with a format string +%% and argements @see io:format/2 +-spec info(t(), string(), [any()]) -> ok. +info(LogState, FormatString, Args) -> + log(LogState, ?EC_INFO, colorize(LogState, ?GREEN, false, FormatString), Args). + +%% @doc log at the error level given the current log state with a string or +%% format string that returns a function +-spec error(t(), string() | log_fun()) -> ok. +error(LogState, Fun) + when erlang:is_function(Fun) -> + log(LogState, ?EC_ERROR, fun() -> + colorize(LogState, ?RED, false, Fun()) + end); +error(LogState, String) -> + error(LogState, "~s~n", [String]). + +%% @doc log at the error level given the current log state with a format string +%% and argements @see io:format/2 +-spec error(t(), string(), [any()]) -> ok. +error(LogState, FormatString, Args) -> + log(LogState, ?EC_ERROR, colorize(LogState, ?GREEN, false, FormatString), Args). + +%% @doc log at the warn level given the current log state with a string or +%% format string that returns a function +-spec warn(t(), string() | log_fun()) -> ok. +warn(LogState, Fun) + when erlang:is_function(Fun) -> + log(LogState, ?EC_WARN, fun() -> colorize(LogState, ?MAGENTA, false, Fun()) end); +warn(LogState, String) -> + warn(LogState, "~s~n", [String]). + +%% @doc log at the warn level given the current log state with a format string +%% and argements @see io:format/2 +-spec warn(t(), string(), [any()]) -> ok. +warn(LogState, FormatString, Args) -> + log(LogState, ?EC_WARN, colorize(LogState, ?MAGENTA, false, FormatString), Args). + +%% @doc Execute the fun passed in if log level is as expected. +-spec log(t(), int_log_level(), log_fun()) -> ok. +log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, Fun) + when DetailLogLevel >= LogLevel -> + io:format("~s~n", [Fun()]); +log(_, _, _) -> + ok. + +%% @doc when the module log level is less then or equal to the log level for the +%% call then write the log info out. When its not then ignore the call. +-spec log(t(), int_log_level(), string(), [any()]) -> ok. +log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, FormatString, Args) + when DetailLogLevel >= LogLevel, + erlang:is_list(Args) -> + io:format(FormatString, Args); +log(_, _, _, _) -> + ok. + +%% @doc return a boolean indicating if the system should log for the specified +%% levelg +-spec should(t(), int_log_level() | any()) -> boolean(). +should(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel) + when DetailLogLevel >= LogLevel -> + true; +should(_, _) -> + false. + +%% @doc get the current log level as an integer +-spec log_level(t()) -> int_log_level(). +log_level(#state_t{mod=?MODULE, log_level=DetailLogLevel}) -> + DetailLogLevel. + +%% @doc get the current log level as an atom +-spec atom_log_level(t()) -> atom_log_level(). +atom_log_level(#state_t{mod=?MODULE, log_level=?EC_ERROR}) -> + error; +atom_log_level(#state_t{mod=?MODULE, log_level=?EC_WARN}) -> + warn; +atom_log_level(#state_t{mod=?MODULE, log_level=?EC_INFO}) -> + info; +atom_log_level(#state_t{mod=?MODULE, log_level=?EC_DEBUG}) -> + debug. + +-spec format(t()) -> iolist(). +format(Log) -> + [<<"(">>, + ec_cnv:to_binary(log_level(Log)), <<":">>, + ec_cnv:to_binary(atom_log_level(Log)), + <<")">>]. + +-spec colorize(t(), color(), boolean(), string()) -> string(). +colorize(#state_t{caller=command_line}, Color, false, Msg) when is_integer(Color) -> + colorize_(Color, 0, Msg); +colorize(_LogState, _Color, _Bold, Msg) -> + Msg. + +-spec colorize_(color(), integer(), string()) -> string(). +colorize_(Color, Bold, Msg) when is_integer(Color), is_integer(Bold)-> + lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [Bold, Color, ?PREFIX, Msg])). + +%%%=================================================================== +%%% Test Functions +%%%=================================================================== + +-ifndef(NOTEST). +-include_lib("eunit/include/eunit.hrl"). + +should_test() -> + ErrorLogState = new(error), + ?assertMatch(true, should(ErrorLogState, ?EC_ERROR)), + ?assertMatch(true, not should(ErrorLogState, ?EC_INFO)), + ?assertMatch(true, not should(ErrorLogState, ?EC_DEBUG)), + ?assertEqual(?EC_ERROR, log_level(ErrorLogState)), + ?assertEqual(error, atom_log_level(ErrorLogState)), + + InfoLogState = new(info), + ?assertMatch(true, should(InfoLogState, ?EC_ERROR)), + ?assertMatch(true, should(InfoLogState, ?EC_INFO)), + ?assertMatch(true, not should(InfoLogState, ?EC_DEBUG)), + ?assertEqual(?EC_INFO, log_level(InfoLogState)), + ?assertEqual(info, atom_log_level(InfoLogState)), + + DebugLogState = new(debug), + ?assertMatch(true, should(DebugLogState, ?EC_ERROR)), + ?assertMatch(true, should(DebugLogState, ?EC_INFO)), + ?assertMatch(true, should(DebugLogState, ?EC_DEBUG)), + ?assertEqual(?EC_DEBUG, log_level(DebugLogState)), + ?assertEqual(debug, atom_log_level(DebugLogState)). + +-endif. From 031db98d27f847ad9ab704bce0f99d314a21008d Mon Sep 17 00:00:00 2001 From: Jordan Wilberding Date: Mon, 14 Oct 2013 13:42:26 -0400 Subject: [PATCH 085/240] Fix travis by not making it run get-deps --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ecf6681..5dae2f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ otp_release: - R14B04 - R14B03 - R14B02 -before_script: "make get-deps" script: "make" branches: only: From 4973a0fb8f3095dfba04bf5d0786691c169d307a Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 13:52:45 -0700 Subject: [PATCH 086/240] fix formatting problems in ec_date --- src/ec_date.erl | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ec_date.erl b/src/ec_date.erl index 55b6b93..6408756 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -92,18 +92,18 @@ do_parse(Date, Now, Opts) -> {error, bad_date} -> erlang:throw({?MODULE, {bad_date, Date}}); {D1, T1} = {{Y, M, D}, {H, M1, S}} - when is_number(Y), is_number(M), - is_number(D), is_number(H), - is_number(M1), is_number(S) -> + when is_number(Y), is_number(M), + is_number(D), is_number(H), + is_number(M1), is_number(S) -> case calendar:valid_date(D1) of true -> {D1, T1}; false -> erlang:throw({?MODULE, {bad_date, Date}}) end; {D1, _T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} - when is_number(Y), is_number(M), - is_number(D), is_number(H), - is_number(M1), is_number(S), - is_number(Ms) -> + when is_number(Y), is_number(M), + is_number(D), is_number(H), + is_number(M1), is_number(S), + is_number(Ms) -> case calendar:valid_date(D1) of true -> {D1, {H,M1,S,Ms}}; false -> erlang:throw({?MODULE, {bad_date, Date}}) @@ -138,17 +138,17 @@ nparse(Date) -> parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $Z ], _Now, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso Year > 31 -> {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, { 0}}; parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $+, Off | _Rest ], _Now, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso Year > 31 -> {{Year, Month, Day}, {hour(Hour, []) - Off, Min, Sec}, {0}}; parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $-, Off | _Rest ], _Now, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> + andalso Year > 31 -> {{Year, Month, Day}, {hour(Hour, []) + Off, Min, Sec}, {0}}; %% Date/Times 22 Aug 2008 6:35.0001 PM @@ -168,7 +168,7 @@ parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> + andalso ?is_year(Year) -> {{Year, Month, Day}, {hour(Hour,[]), Min, Sec}, {Ms}}; parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms], _Now, _Opts) when ?is_us_sep(X) andalso ?is_month(Month) -> @@ -180,21 +180,21 @@ parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms ], _Now, _Opts) %% Date/Times Dec 1st, 2012 6:25 PM parse([Month,Day,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; + {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; parse([Month,Day,Year,Hour,$:,Min | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; + {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; parse([Month,Day,Year,Hour | PAM], _Now, _Opts) when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; %% Date/Times Dec 1st, 2012 18:25:15 (no AM/PM) parse([Month,Day,Year,Hour,$:,Min,$:,Sec], _Now, _Opts) when ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, []), Min, Sec}}; + {{Year, Month, Day}, {hour(Hour, []), Min, Sec}}; parse([Month,Day,Year,Hour,$:,Min], _Now, _Opts) when ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, []), Min, 0}}; + {{Year, Month, Day}, {hour(Hour, []), Min, 0}}; %% Times - 21:45, 13:45:54, 13:15PM etc parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> @@ -243,7 +243,7 @@ parse([Day,X,Month,X,Year,Hour | PAM], _Date, _Opts) {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; parse([Month,X,Day,X,Year,Hour | PAM], _Date, _Opts) when ?is_meridian(PAM) andalso ?is_us_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; + {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; %% Time is "6:35 PM" ms return @@ -675,7 +675,7 @@ ltoi(X) -> %% TEST FUNCTIONS %% %% c(dh_date,[{d,'TEST'}]). -%-define(NOTEST, 1). +%%-define(NOTEST, 1). -include_lib("eunit/include/eunit.hrl"). From 16b441f0e32c1f528f9240aae55ef32ce8892bac Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 14:10:25 -0700 Subject: [PATCH 087/240] fix up tests to reflect the actual NOTEST variable DEV_ONLY --- src/ec_cmd_log.erl | 2 +- src/ec_cnv.erl | 6 +++--- src/ec_date.erl | 11 ++++++----- src/ec_file.erl | 2 +- src/ec_gb_trees.erl | 2 +- src/ec_lists.erl | 2 +- src/ec_semver.erl | 2 +- src/ec_talk.erl | 7 +++++-- test/ec_plists_tests.erl | 4 ++++ test/mock.erl | 10 ---------- 10 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 test/mock.erl diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 0be4143..4038eee 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -227,7 +227,7 @@ colorize_(Color, Bold, Msg) when is_integer(Color), is_integer(Bold)-> %%% Test Functions %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). should_test() -> diff --git a/src/ec_cnv.erl b/src/ec_cnv.erl index a063e2a..80b05e7 100644 --- a/src/ec_cnv.erl +++ b/src/ec_cnv.erl @@ -33,7 +33,7 @@ is_true/1, is_false/1]). --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("proper/include/proper.hrl"). -endif. @@ -218,10 +218,10 @@ to_atom(X) -> to_atom(to_list(X)). %%%=================================================================== -%%% API +%%% Tests %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). force_proper_test_() -> diff --git a/src/ec_date.erl b/src/ec_date.erl index 6408756..73eb15d 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -671,14 +671,14 @@ pad2(X) when is_float(X) -> ltoi(X) -> list_to_integer(X). -%% -%% TEST FUNCTIONS -%% -%% c(dh_date,[{d,'TEST'}]). -%%-define(NOTEST, 1). +%%%=================================================================== +%%% Tests +%%%=================================================================== +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). + -define(DATE, {{2001,3,10},{17,16,17}}). -define(DATEMS, {{2001,3,10},{17,16,17,123456}}). -define(DATE_NOON, {{2001,3,10},{12,0,0}}). @@ -938,3 +938,4 @@ zulu_test_() -> ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04:00")), "2001-03-10T19:16:17") ]. +-endif. diff --git a/src/ec_file.erl b/src/ec_file.erl index 92430cd..499a406 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -298,7 +298,7 @@ sub_files(From) -> %%% Test Functions %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). setup_test() -> diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl index 811cd1b..50d9701 100644 --- a/src/ec_gb_trees.erl +++ b/src/ec_gb_trees.erl @@ -154,7 +154,7 @@ keys(Data) -> %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). %% For me unit testing initially is about covering the obvious case. A diff --git a/src/ec_lists.erl b/src/ec_lists.erl index 689813e..fd8fa5f 100644 --- a/src/ec_lists.erl +++ b/src/ec_lists.erl @@ -68,7 +68,7 @@ fetch(Fun, List) when is_list(List), is_function(Fun) -> %%% Test Functions %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). find1_test() -> diff --git a/src/ec_semver.erl b/src/ec_semver.erl index bf4e157..23ba311 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -314,7 +314,7 @@ internal_pes(Vsn, LVsn) -> %%% Test Functions %%%=================================================================== --ifndef(NOTEST). +-ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). eql_test() -> diff --git a/src/ec_talk.erl b/src/ec_talk.erl index 936f9ed..243f7b4 100644 --- a/src/ec_talk.erl +++ b/src/ec_talk.erl @@ -43,8 +43,6 @@ type/0, supported/0]). --include_lib("eunit/include/eunit.hrl"). - %%============================================================================ %% Types %%============================================================================ @@ -202,6 +200,9 @@ get_string(String) -> %%%==================================================================== %%% tests %%%==================================================================== +-ifdef(DEV_ONLY). +-include_lib("eunit/include/eunit.hrl"). + general_test_() -> [?_test(42 == get_integer("42")), ?_test(500211 == get_integer("500211")), @@ -216,3 +217,5 @@ general_test_() -> ?_test(false == get_boolean("False")), ?_test(false == get_boolean("No")), ?_test(false == get_boolean("no"))]. + +-endif. diff --git a/test/ec_plists_tests.erl b/test/ec_plists_tests.erl index 7acefe6..ff5d2e9 100644 --- a/test/ec_plists_tests.erl +++ b/test/ec_plists_tests.erl @@ -1,6 +1,8 @@ %%% @copyright Erlware, LLC. -module(ec_plists_tests). +-ifdef(DEV_ONLY). + -include_lib("eunit/include/eunit.hrl"). %%%=================================================================== @@ -73,3 +75,5 @@ ftmap_bad_test() -> lists:seq(1, 5)), ?assertMatch([{value, 1}, {error,{throw,test_exception}}, {value, 3}, {value, 4}, {value, 5}] , Results). + +-endif. diff --git a/test/mock.erl b/test/mock.erl deleted file mode 100644 index ad7c6bd..0000000 --- a/test/mock.erl +++ /dev/null @@ -1,10 +0,0 @@ --module(mock). - --export([new_dictionary/0]). - -new_dictionary() -> - meck:new(ec_dictionary_proper), - meck:expect(ec_dictionary_proper, dictionary, fun() -> - proper_types:union([ec_dict]) - end). - From 54f568e8262b8f309ce8bc8cb9f4102da9e726c5 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 14:10:47 -0700 Subject: [PATCH 088/240] update the ec_semver_parser --- src/ec_semver_parser.erl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl index ba68238..ac4ddb7 100644 --- a/src/ec_semver_parser.erl +++ b/src/ec_semver_parser.erl @@ -1,4 +1,3 @@ -%%% vi:ts=4 sw=4 et -module(ec_semver_parser). -export([parse/1,file/1]). -compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). @@ -6,7 +5,7 @@ -compile(export_all). -spec file(file:name()) -> any(). -file(Filename) -> {ok, Bin} = file:read_file(Filename), parse(Bin). +file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -> Err end. -spec parse(binary() | list()) -> any(). parse(List) when is_list(List) -> parse(list_to_binary(List)); @@ -19,19 +18,19 @@ parse(Input) when is_binary(Input) -> release_memo(), Result. 'semver'(Input, Index) -> - p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). + p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). 'major_minor_patch_min_patch'(Input, Index) -> - p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) -> transform('major_minor_patch_min_patch', Node, Idx) end). + p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end). 'version_part'(Input, Index) -> - p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) -> transform('version_part', Node, Idx) end). + p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end). 'numeric_part'(Input, Index) -> - p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) -> erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). + p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). 'alpha_part'(Input, Index) -> - p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) -> erlang:iolist_to_binary(Node) end). + p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). transform(_,Node,_Index) -> Node. From efdd2a10926e75de89e3a8065a43f766d13475d7 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 16:19:08 -0700 Subject: [PATCH 089/240] fix dialyzer issues --- src/ec_cmd_log.erl | 27 +++++++++++++++------------ src/ec_file.erl | 8 ++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 4038eee..42250e6 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -49,9 +49,8 @@ -define(PREFIX, "===> "). --record(state_t, {mod=?MODULE :: ec_log, - log_level=0 :: int_log_level(), - caller=api :: api | command_line}). +-record(state_t, {log_level=0 :: int_log_level(), + caller=api :: caller()}). %%============================================================================ %% types @@ -60,8 +59,11 @@ int_log_level/0, atom_log_level/0, log_level/0, + caller/0, log_fun/0]). +-type caller() :: api | command_line. + -type log_level() :: int_log_level() | atom_log_level(). -type int_log_level() :: 0..3. @@ -82,8 +84,9 @@ new(LogLevel) -> new(LogLevel, api). +-spec new(log_level(), caller()) -> t(). new(LogLevel, Caller) when LogLevel >= 0, LogLevel =< 3 -> - #state_t{mod=?MODULE, log_level=LogLevel, caller=Caller}; + #state_t{log_level=LogLevel, caller=Caller}; new(AtomLogLevel, Caller) when AtomLogLevel =:= error; AtomLogLevel =:= warn; @@ -165,7 +168,7 @@ warn(LogState, FormatString, Args) -> %% @doc Execute the fun passed in if log level is as expected. -spec log(t(), int_log_level(), log_fun()) -> ok. -log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, Fun) +log(#state_t{log_level=DetailLogLevel}, LogLevel, Fun) when DetailLogLevel >= LogLevel -> io:format("~s~n", [Fun()]); log(_, _, _) -> @@ -174,7 +177,7 @@ log(_, _, _) -> %% @doc when the module log level is less then or equal to the log level for the %% call then write the log info out. When its not then ignore the call. -spec log(t(), int_log_level(), string(), [any()]) -> ok. -log(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel, FormatString, Args) +log(#state_t{log_level=DetailLogLevel}, LogLevel, FormatString, Args) when DetailLogLevel >= LogLevel, erlang:is_list(Args) -> io:format(FormatString, Args); @@ -184,7 +187,7 @@ log(_, _, _, _) -> %% @doc return a boolean indicating if the system should log for the specified %% levelg -spec should(t(), int_log_level() | any()) -> boolean(). -should(#state_t{mod=?MODULE, log_level=DetailLogLevel}, LogLevel) +should(#state_t{log_level=DetailLogLevel}, LogLevel) when DetailLogLevel >= LogLevel -> true; should(_, _) -> @@ -192,18 +195,18 @@ should(_, _) -> %% @doc get the current log level as an integer -spec log_level(t()) -> int_log_level(). -log_level(#state_t{mod=?MODULE, log_level=DetailLogLevel}) -> +log_level(#state_t{log_level=DetailLogLevel}) -> DetailLogLevel. %% @doc get the current log level as an atom -spec atom_log_level(t()) -> atom_log_level(). -atom_log_level(#state_t{mod=?MODULE, log_level=?EC_ERROR}) -> +atom_log_level(#state_t{log_level=?EC_ERROR}) -> error; -atom_log_level(#state_t{mod=?MODULE, log_level=?EC_WARN}) -> +atom_log_level(#state_t{log_level=?EC_WARN}) -> warn; -atom_log_level(#state_t{mod=?MODULE, log_level=?EC_INFO}) -> +atom_log_level(#state_t{log_level=?EC_INFO}) -> info; -atom_log_level(#state_t{mod=?MODULE, log_level=?EC_DEBUG}) -> +atom_log_level(#state_t{log_level=?EC_DEBUG}) -> debug. -spec format(t()) -> iolist(). diff --git a/src/ec_file.erl b/src/ec_file.erl index 499a406..3f94bc2 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -175,7 +175,7 @@ mkdir_path(Path) -> %% @doc read a file from the file system. Provide UEX exeption on failure. --spec read(FilePath::file:filename()) -> binary() | {error, Reason::term()}. +-spec read(FilePath::file:filename()) -> {ok, binary()} | {error, Reason::term()}. read(FilePath) -> %% Now that we are moving away from exceptions again this becomes %% a bit redundant but we want to be backwards compatible as much @@ -373,9 +373,9 @@ find_test() -> {BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(), Result = find(BaseDir, "file[a-z]+\$"), ?assertMatch(3, erlang:length(Result)), - ?assert(lists:member(Name1, Result)), - ?assert(lists:member(Name2, Result)), - ?assert(lists:member(Name3, Result)), + ?assertEqual(true, lists:member(Name1, Result)), + ?assertEqual(true, lists:member(Name2, Result)), + ?assertEqual(true, lists:member(Name3, Result)), remove(BaseDir, [recursive]). -endif. From b8dc0eed6d7bd39c6d4091b1b1f1fa37a1db59d3 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 14 Oct 2013 17:05:52 -0700 Subject: [PATCH 090/240] make sure that travis runs dialyzer --- .travis.yml | 3 +-- Makefile | 45 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5dae2f4..6490e13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ otp_release: - R14B04 - R14B03 - R14B02 -script: "make" +script: "make rebuild" branches: only: - master - - next diff --git a/Makefile b/Makefile index e05f06a..47acb32 100644 --- a/Makefile +++ b/Makefile @@ -3,22 +3,49 @@ # BSD License see COPYING ERL = $(shell which erl) -ERL_VER = $(shell erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell) +ERL_VER = $(shell erl -eval 'io:format("~s", [erlang:system_info(otp_release)]), halt().' -noshell) +ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/*/ebin +# ============================================================================= +# Verify that the programs we need to run are installed on this system +# ============================================================================= + REBAR=$(shell which rebar) ifeq ($(REBAR),) $(error "Rebar not available on this system") endif -ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt +# ============================================================================= +# Handle version discovery +# ============================================================================= + +# We have a problem that we only have 10 minutes to build on travis +# and those travis boxes are quite small. This is ok for the fast +# dialyzer on R15 and above. However on R14 and below we have the +# problem that travis times out. The code below lets us not run +# dialyzer on R14 +OTP_VSN=$(shell erl -noshell -eval 'io:format("~p", [erlang:system_info(otp_release)]), erlang:halt(0).' | perl -lne 'print for /R(\d+).*/g') +TRAVIS_SLOW=$(shell expr $(OTP_VSN) \<= 15 ) + +ifeq ($(TRAVIS_SLOW), 0) +DIALYZER=$(shell which dialyzer) +else +DIALYZER=: not running dialyzer on R14 or R15 +endif + +# ============================================================================= +# Rules to build the system +# ============================================================================= .PHONY: all compile doc clean test shell distclean pdf get-deps rebuild dialyzer typer all: compile doc test +rebuild: distclean deps compile dialyzer test + deps: .DEV_MODE $(REBAR) get-deps compile @@ -43,29 +70,29 @@ $(ERLWARE_COMMONS_PLT).$(ERL_VER).erts: @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + - $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).erts --build_plt \ --apps erts $(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel:$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + - $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel --build_plt \ --apps kernel $(ERLWARE_COMMONS_PLT).$(ERL_VER).base:$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo - - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ + - $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \ --apps stdlib $(ERLWARE_COMMONS_PLT).$(ERL_VER): $(ERLWARE_COMMONS_PLT).$(ERL_VER).base @echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER) @echo - - dialyzer --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) --add_to_plt --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base \ + - $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) --add_to_plt --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base \ --apps eunit -r deps -dialyzer: $(ERLWARE_COMMONS_PLT).$(ERL_VER) - dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -Wrace_conditions -r ./ebin +dialyzer: compile $(ERLWARE_COMMONS_PLT).$(ERL_VER) + $(DIALYZER) --fullpath --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -Wrace_conditions -r ./ebin typer: $(ERLWARE_COMMONS_PLT).$(ERL_VER) typer --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -r ./src @@ -90,5 +117,3 @@ distclean: clean rm -rf $(ERLWARE_COMMONS_PLT).$(ERL_VER) rm -rvf $(CURDIR)/deps rm -rvf .DEV_MODE - -rebuild: distclean all From 06390816b9671f3093a2e3db5d0230a757996397 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 24 Oct 2013 13:18:09 -0500 Subject: [PATCH 091/240] fix includings of headers --- src/ec_cmd_log.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 42250e6..e61e67a 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -38,7 +38,7 @@ atom_log_level/1, format/1]). --include_lib("erlware_commons/include/ec_cmd_log.hrl"). +-include("ec_cmd_log.hrl"). -define(RED, 31). -define(GREEN, 32). From b9a2681a326a5066e4c34a5e8938cad0484d708c Mon Sep 17 00:00:00 2001 From: Jordan Wilberding Date: Fri, 25 Oct 2013 12:39:02 -0400 Subject: [PATCH 092/240] Add irc notifications --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6490e13..ddbaffb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,11 @@ script: "make rebuild" branches: only: - master +notifications: + email: + - core@erlware.org + irc: + channels: + - "irc.freenode.org#erlware" + use_notice: true + skip_join: true \ No newline at end of file From f821e33806b8eb3794ca8960efd9f6590e99b629 Mon Sep 17 00:00:00 2001 From: Kamil Kieliszczyk Date: Wed, 19 Feb 2014 12:07:15 +0100 Subject: [PATCH 093/240] Add R16Bx and 17.0-rc1 to .travis.yml --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6490e13..f3f11de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,10 @@ language: erlang otp_release: + - 17.0-rc1 + - R16B03-1 + - R16B03 + - R16B02 + - R16B01 - R16B - R15B02 - R15B01 From 741bba1b82e834e1515ca7f5c8f02769c75a352c Mon Sep 17 00:00:00 2001 From: Kamil Kieliszczyk Date: Wed, 19 Feb 2014 12:17:57 +0100 Subject: [PATCH 094/240] Make erlware_commons be compatible with Erlang 17.0-rc1 --- rebar.config.script | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config.script b/rebar.config.script index bbe043f..6519616 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -13,7 +13,7 @@ MergeConfig = fun({Key, ToAdd}, C) -> end end. -{match, [ErtsNumber]} = re:run(erlang:system_info(otp_release), "R(\\d+).+", [{capture, [1], list}]), +{match, [ErtsNumber]} = re:run(erlang:system_info(otp_release), "(\\d+)", [{capture, [0], list}]), ErtsVsn = erlang:list_to_integer(ErtsNumber), AddErlOpts = if ErtsVsn >= 15 -> From d9a83413afa2588662f1c1dfa7213fc695dec7e8 Mon Sep 17 00:00:00 2001 From: Roger Lipscombe Date: Wed, 19 Mar 2014 12:38:07 +0000 Subject: [PATCH 095/240] Allow overriding rebar location. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 47acb32..0269ee8 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/*/ebin # Verify that the programs we need to run are installed on this system # ============================================================================= -REBAR=$(shell which rebar) +REBAR ?= $(shell which rebar) ifeq ($(REBAR),) $(error "Rebar not available on this system") From 47bcbd49b6fdef020cf190c20a13856dd86c0577 Mon Sep 17 00:00:00 2001 From: Eric B Merritt Date: Tue, 25 Mar 2014 17:01:20 -0700 Subject: [PATCH 096/240] Suppport a vsn signature with a git implementation --- rebar.config | 2 +- src/ec_git_vsn.erl | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/ec_vsn.erl | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/ec_git_vsn.erl create mode 100644 src/ec_vsn.erl diff --git a/rebar.config b/rebar.config index 6bc7d6f..057e498 100644 --- a/rebar.config +++ b/rebar.config @@ -5,7 +5,7 @@ {git, "https://github.com/erlware/rebar_vsn_plugin.git", {branch, "master"}}}]}. -{erl_first_files, ["ec_dictionary"]}. +{erl_first_files, ["ec_dictionary", "ec_vsn"]}. %% Compiler Options ============================================================ {erl_opts, diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl new file mode 100644 index 0000000..21d2639 --- /dev/null +++ b/src/ec_git_vsn.erl @@ -0,0 +1,79 @@ +%%% vi:ts=4 sw=4 et +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2011 Erlware, LLC. +%%% @doc +%%% This provides an implementation of the ec_vsn for git. That is +%%% it is capable of returning a semver for a git repository +%%% see ec_vsn +%%% see ec_semver +%%% @end +%%%------------------------------------------------------------------- +-module(ec_git_vsn). + +-behaviour(ec_vsn). + +%% API +-export([new/0, + vsn/1]). + +-export_type([t/0]). + +%%%=================================================================== +%%% Types +%%%=================================================================== +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type t() :: {}. + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec new() -> t(). +new() -> + {}. + +-spec vsn(t()) -> {ok, string()} | {error, Reason::any()}. +vsn(_Data) -> + Result = do_cmd("git describe --tags --always"), + case re:split(Result, "-") of + [Vsn, Count, RefTag] -> + erlang:iolist_to_binary([strip_leading_v(Vsn), + <<"+build.">>, + Count, + <<".ref.">>, + RefTag]); + [VsnOrRefTag] -> + case re:run(VsnOrRefTag, "^[0-9a-fA-F]+$") of + {match, _} -> + find_vsn_from_start_of_branch(VsnOrRefTag); + nomatch -> + strip_leading_v(VsnOrRefTag) + end; + _ -> + {error, {invalid_result, Result}} + end. + +%%%=================================================================== +%%% Internal Functions +%%%=================================================================== +-spec strip_leading_v(string()) -> string(). +strip_leading_v(Vsn) -> + case re:run(Vsn, "v?(.+)", [{capture, [1], binary}]) of + {match, [NVsn]} -> + NVsn; + _ -> + Vsn + end. + +-spec find_vsn_from_start_of_branch(string()) -> string(). +find_vsn_from_start_of_branch(RefTag) -> + Count = do_cmd("git rev-list HEAD --count"), + erlang:iolist_to_binary("0.0.0+build.", Count, ".ref.", RefTag). + +do_cmd(Cmd) -> + trim_whitespace(os:cmd(Cmd)). + +trim_whitespace(Input) -> + re:replace(Input, "\\s+", "", [global]). diff --git a/src/ec_vsn.erl b/src/ec_vsn.erl new file mode 100644 index 0000000..2f38090 --- /dev/null +++ b/src/ec_vsn.erl @@ -0,0 +1,66 @@ +%%% vi:ts=4 sw=4 et +%%%------------------------------------------------------------------- +%%% @author Eric Merritt +%%% @copyright 2014 Erlware, LLC. +%%% @doc +%%% Provides a signature to manage returning semver formatted versions +%%% from various version control repositories. +%%% +%%% This interface is a member of the Erlware Commons Library. +%%% @end +%%%------------------------------------------------------------------- +-module(ec_vsn). + +%% API +-export([new/1, + vsn/1]). + +-export_type([t/0]). + +%%%=================================================================== +%%% Types +%%%=================================================================== + +-record(t, {callback, data}). + +%% This should be opaque, but that kills dialyzer so for now we export it +%% however you should not rely on the internal representation here +-type t() :: #t{}. + +-ifdef(have_callback_support). + +-callback new() -> any(). +-callback vsn(any()) -> {ok, string()} | {error, Reason::any()}. + +-else. + +%% In the case where R14 or lower is being used to compile the system +%% we need to export a behaviour info +-export([behaviour_info/1]). +-spec behaviour_info(atom()) -> [{atom(), arity()}] | undefined. +behaviour_info(callbacks) -> + [{new, 0}, + {vsn, 1}]; +behaviour_info(_Other) -> + undefined. +-endif. + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc create a new dictionary object from the specified module. The +%% module should implement the dictionary behaviour. +%% +%% @param ModuleName The module name. +-spec new(module()) -> t(). +new(ModuleName) when erlang:is_atom(ModuleName) -> + #t{callback = ModuleName, data = ModuleName:new()}. + +%% @doc Return the semver or an error depending on what is possible +%% with this implementation in this directory. +%% +%% @param The dictionary object +-spec vsn(t()) -> {ok, string()} | {error, Reason::any()}. +vsn(#t{callback = Mod, data = Data}) -> + Mod:vsn(Data). From 449051bcd69eaff29fbda822bf4017f2ebdab0c5 Mon Sep 17 00:00:00 2001 From: Jordan Wilberding Date: Fri, 28 Mar 2014 08:39:26 +0100 Subject: [PATCH 097/240] Fix argument for iolist_to_binary call --- src/ec_git_vsn.erl | 2 +- src/ec_semver_parser.erl | 92 +++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl index 21d2639..f06ea8e 100644 --- a/src/ec_git_vsn.erl +++ b/src/ec_git_vsn.erl @@ -70,7 +70,7 @@ strip_leading_v(Vsn) -> -spec find_vsn_from_start_of_branch(string()) -> string(). find_vsn_from_start_of_branch(RefTag) -> Count = do_cmd("git rev-list HEAD --count"), - erlang:iolist_to_binary("0.0.0+build.", Count, ".ref.", RefTag). + erlang:iolist_to_binary(["0.0.0+build.", Count, ".ref.", RefTag]). do_cmd(Cmd) -> trim_whitespace(os:cmd(Cmd)). diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl index ac4ddb7..7aeeec1 100644 --- a/src/ec_semver_parser.erl +++ b/src/ec_semver_parser.erl @@ -1,6 +1,15 @@ -module(ec_semver_parser). -export([parse/1,file/1]). --compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). +-define(p_anything,true). +-define(p_charclass,true). +-define(p_choose,true). +-define(p_not,true). +-define(p_one_or_more,true). +-define(p_optional,true). +-define(p_scan,true). +-define(p_seq,true). +-define(p_string,true). +-define(p_zero_or_more,true). -compile(export_all). @@ -10,34 +19,45 @@ file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err - -spec parse(binary() | list()) -> any(). parse(List) when is_list(List) -> parse(list_to_binary(List)); parse(Input) when is_binary(Input) -> - setup_memo(), + _ = setup_memo(), Result = case 'semver'(Input,{{line,1},{column,1}}) of {AST, <<>>, _Index} -> AST; Any -> Any end, release_memo(), Result. +-spec 'semver'(input(), index()) -> parse_result(). 'semver'(Input, Index) -> p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). +-spec 'major_minor_patch_min_patch'(input(), index()) -> parse_result(). 'major_minor_patch_min_patch'(Input, Index) -> p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end). +-spec 'version_part'(input(), index()) -> parse_result(). 'version_part'(Input, Index) -> p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end). +-spec 'numeric_part'(input(), index()) -> parse_result(). 'numeric_part'(Input, Index) -> p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). +-spec 'alpha_part'(input(), index()) -> parse_result(). 'alpha_part'(Input, Index) -> p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). transform(_,Node,_Index) -> Node. +-file("peg_includes.hrl", 1). +-type index() :: {{line, pos_integer()}, {column, pos_integer()}}. +-type input() :: binary(). +-type parse_failure() :: {fail, term()}. +-type parse_success() :: {term(), input(), index()}. +-type parse_result() :: parse_failure() | parse_success(). +-type parse_fun() :: fun((input(), index()) -> parse_result()). +-type xform_fun() :: fun((input(), index()) -> term()). -p(Inp, Index, Name, ParseFun) -> - p(Inp, Index, Name, ParseFun, fun(N, _Idx) -> N end). - +-spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result(). p(Inp, StartIndex, Name, ParseFun, TransformFun) -> case get_memo(StartIndex, Name) of % See if the current reduction is memoized {ok, Memo} -> %Memo; % If it is, return the stored result @@ -54,12 +74,15 @@ p(Inp, StartIndex, Name, ParseFun, TransformFun) -> Result end. +-spec setup_memo() -> ets:tid(). setup_memo() -> put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])). +-spec release_memo() -> true. release_memo() -> ets:delete(memo_table_name()). +-spec memoize(index(), atom(), parse_result()) -> true. memoize(Index, Name, Result) -> Memo = case ets:lookup(memo_table_name(), Index) of [] -> []; @@ -67,6 +90,7 @@ memoize(Index, Name, Result) -> end, ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}). +-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}. get_memo(Index, Name) -> case ets:lookup(memo_table_name(), Index) of [] -> {error, not_found}; @@ -77,13 +101,19 @@ get_memo(Index, Name) -> end end. +-spec memo_table_name() -> ets:tid(). memo_table_name() -> get({parse_memo_table, ?MODULE}). +-ifdef(p_eof). +-spec p_eof() -> parse_fun(). p_eof() -> fun(<<>>, Index) -> {eof, [], Index}; (_, Index) -> {fail, {expected, eof, Index}} end. +-endif. +-ifdef(p_optional). +-spec p_optional(parse_fun()) -> parse_fun(). p_optional(P) -> fun(Input, Index) -> case P(Input, Index) of @@ -91,7 +121,10 @@ p_optional(P) -> {_, _, _} = Success -> Success end end. +-endif. +-ifdef(p_not). +-spec p_not(parse_fun()) -> parse_fun(). p_not(P) -> fun(Input, Index)-> case P(Input,Index) of @@ -100,7 +133,10 @@ p_not(P) -> {Result, _, _} -> {fail, {expected, {no_match, Result},Index}} end end. +-endif. +-ifdef(p_assert). +-spec p_assert(parse_fun()) -> parse_fun(). p_assert(P) -> fun(Input,Index) -> case P(Input,Index) of @@ -108,27 +144,32 @@ p_assert(P) -> _ -> {[], Input, Index} end end. +-endif. -p_and(P) -> - p_seq(P). - +-ifdef(p_seq). +-spec p_seq([parse_fun()]) -> parse_fun(). p_seq(P) -> fun(Input, Index) -> p_all(P, Input, Index, []) end. +-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result(). p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index}; p_all([P|Parsers], Inp, Index, Accum) -> case P(Inp, Index) of {fail, _} = Failure -> Failure; {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum]) end. +-endif. +-ifdef(p_choose). +-spec p_choose([parse_fun()]) -> parse_fun(). p_choose(Parsers) -> fun(Input, Index) -> p_attempt(Parsers, Input, Index, none) end. +-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result(). p_attempt([], _Input, _Index, Failure) -> Failure; p_attempt([P|Parsers], Input, Index, FirstFailure)-> case P(Input, Index) of @@ -139,12 +180,18 @@ p_attempt([P|Parsers], Input, Index, FirstFailure)-> end; Result -> Result end. +-endif. +-ifdef(p_zero_or_more). +-spec p_zero_or_more(parse_fun()) -> parse_fun(). p_zero_or_more(P) -> fun(Input, Index) -> p_scan(P, Input, Index, []) end. +-endif. +-ifdef(p_one_or_more). +-spec p_one_or_more(parse_fun()) -> parse_fun(). p_one_or_more(P) -> fun(Input, Index)-> Result = p_scan(P, Input, Index, []), @@ -156,7 +203,10 @@ p_one_or_more(P) -> {fail, {expected, {at_least_one, Failure}, Index}} end end. +-endif. +-ifdef(p_label). +-spec p_label(atom(), parse_fun()) -> parse_fun(). p_label(Tag, P) -> fun(Input, Index) -> case P(Input, Index) of @@ -166,15 +216,20 @@ p_label(Tag, P) -> {{Tag, Result}, InpRem, NewIndex} end end. +-endif. -p_scan(_, [], Index, Accum) -> {lists:reverse( Accum ), [], Index}; +-ifdef(p_scan). +-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}. +p_scan(_, <<>>, Index, Accum) -> {lists:reverse(Accum), <<>>, Index}; p_scan(P, Inp, Index, Accum) -> case P(Inp, Index) of {fail,_} -> {lists:reverse(Accum), Inp, Index}; {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum]) end. +-endif. -p_string(S) when is_list(S) -> p_string(list_to_binary(S)); +-ifdef(p_string). +-spec p_string(binary()) -> parse_fun(). p_string(S) -> Length = erlang:byte_size(S), fun(Input, Index) -> @@ -185,14 +240,20 @@ p_string(S) -> error:{badmatch,_} -> {fail, {expected, {string, S}, Index}} end end. +-endif. +-ifdef(p_anything). +-spec p_anything() -> parse_fun(). p_anything() -> fun(<<>>, Index) -> {fail, {expected, any_character, Index}}; (Input, Index) when is_binary(Input) -> <> = Input, {<>, Rest, p_advance_index(<>, Index)} end. +-endif. +-ifdef(p_charclass). +-spec p_charclass(string() | binary()) -> parse_fun(). p_charclass(Class) -> {ok, RE} = re:compile(Class, [unicode, dotall]), fun(Inp, Index) -> @@ -203,7 +264,10 @@ p_charclass(Class) -> _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}} end end. +-endif. +-ifdef(p_regexp). +-spec p_regexp(binary()) -> parse_fun(). p_regexp(Regexp) -> {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]), fun(Inp, Index) -> @@ -214,13 +278,21 @@ p_regexp(Regexp) -> _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}} end end. +-endif. +-ifdef(line). +-spec line(index() | term()) -> pos_integer() | undefined. line({{line,L},_}) -> L; line(_) -> undefined. +-endif. +-ifdef(column). +-spec column(index() | term()) -> pos_integer() | undefined. column({_,{column,C}}) -> C; column(_) -> undefined. +-endif. +-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index(). p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput)); p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters From 523a66ad7448cf4b49c6b803f1198e5b3e2c7960 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 22 Apr 2014 10:32:44 -0500 Subject: [PATCH 098/240] handle deprecated pre-defined types for 17.0 and later --- rebar.config | 3 ++- src/ec_dict.erl | 4 ++++ src/ec_plists.erl | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 057e498..07a123c 100644 --- a/rebar.config +++ b/rebar.config @@ -9,7 +9,8 @@ %% Compiler Options ============================================================ {erl_opts, - [debug_info, + [{platform_define, "^[0-9]+", namespaced_types}, + debug_info, warnings_as_errors]}. %% EUnit ======================================================================= diff --git a/src/ec_dict.erl b/src/ec_dict.erl index 49f3d96..0c0b998 100644 --- a/src/ec_dict.erl +++ b/src/ec_dict.erl @@ -34,7 +34,11 @@ %%%=================================================================== %% This should be opaque, but that kills dialyzer so for now we export it %% however you should not rely on the internal representation here +-ifdef(namespaced_types). +-type dictionary(_K, _V) :: dict:dict(). +-else. -type dictionary(_K, _V) :: dict(). +-endif. %%%=================================================================== %%% API diff --git a/src/ec_plists.erl b/src/ec_plists.erl index 7512fdc..4726c18 100644 --- a/src/ec_plists.erl +++ b/src/ec_plists.erl @@ -480,9 +480,17 @@ usort(Fun, List, Malt) -> runmany(Fun2, {recursive, Fuse}, List, Malt). %% @doc Like below, assumes default MapMalt of 1. +-ifdef(namespaced_types). +-spec mapreduce/2 :: (MapFunc, list()) -> dict:dict() when + MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), + DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}. +-else. -spec mapreduce/2 :: (MapFunc, list()) -> dict() when MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}. +-endif. + + mapreduce(MapFunc, List) -> mapreduce(MapFunc, List, 1). @@ -510,10 +518,17 @@ mapreduce(MapFunc, List, MapMalt) -> %% %% mapreduce requires OTP R11B, or it may leave monitoring messages in the %% message queue. +-ifdef(namespaced_types). +-spec mapreduce/5 :: (MapFunc, list(), InitState::term(), ReduceFunc, malt()) -> dict:dict() when + MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), + DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}, + ReduceFunc :: fun((OldState::term(), Key::term(), Value::term()) -> NewState::term()). +-else. -spec mapreduce/5 :: (MapFunc, list(), InitState::term(), ReduceFunc, malt()) -> dict() when MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}, ReduceFunc :: fun((OldState::term(), Key::term(), Value::term()) -> NewState::term()). +-endif. mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> Parent = self(), {Reducer, ReducerRef} = From e2841d6cefb5a77e969646882e37296be1bc4972 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 22 Apr 2014 12:13:26 -0500 Subject: [PATCH 099/240] remove 17.0rc1 from travis, wait for travis 17.0 support --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a4792d9..0f74d91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: erlang otp_release: - - 17.0-rc1 - R16B03-1 - R16B03 - R16B02 From bd6fd557d587be8d2bb3787d9bf9b4c9d6371351 Mon Sep 17 00:00:00 2001 From: Low Kian Seong Date: Thu, 8 May 2014 11:10:38 +0800 Subject: [PATCH 100/240] Found a typo while reading docs. Correcting --- src/ec_file.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index 3f94bc2..cda2ca1 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -143,7 +143,7 @@ real_dir_path(Path) -> ok = file:set_cwd(CurCwd), filename:absname(RealPath). -%% @doc make a unique temorory directory. Similar function to BSD stdlib +%% @doc make a unique temporary directory. Similar function to BSD stdlib %% function of the same name. -spec insecure_mkdtemp() -> TmpDirPath::file:name(). insecure_mkdtemp() -> From cc7f6dd0dfaeaa00b92d25ac5ffe2cde06987249 Mon Sep 17 00:00:00 2001 From: Low Kian Seong Date: Wed, 14 May 2014 22:42:59 +0800 Subject: [PATCH 101/240] changes to add another clause to the directory/file check --- src/ec_file.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index cda2ca1..46f14e9 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -118,7 +118,7 @@ is_symlink(Path) -> false end. %% @doc returns the type of the file. --spec type(file:name()) -> file | symlink | directory. +-spec type(file:name()) -> file | symlink | directory | undefined. type(Path) -> case filelib:is_regular(Path) of true -> @@ -126,10 +126,13 @@ type(Path) -> false -> case is_symlink(Path) of true -> - symlink; - false -> - directory + symlink; + false -> case filelib:is_dir(Path) of + true -> directory; + false -> undefined + end end + end. %% @doc gets the real path of a directory. This is mostly useful for %% resolving symlinks. Be aware that this temporarily changes the From d1d19e32480b43aa9972a3998b1b1295fa0914d1 Mon Sep 17 00:00:00 2001 From: Jordan Wilberding Date: Sat, 12 Apr 2014 11:38:19 +0200 Subject: [PATCH 102/240] Update to use official 17.0 release for Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0f74d91..bf58212 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: erlang otp_release: + - 17.0 - R16B03-1 - R16B03 - R16B02 From 73f21ee770457f93cc9cc7897664721bfe0b8654 Mon Sep 17 00:00:00 2001 From: Low Kian Seong Date: Fri, 16 May 2014 10:38:13 +0800 Subject: [PATCH 103/240] Adding sha1sum method --- src/ec_file.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ec_file.erl b/src/ec_file.erl index 46f14e9..3fe8a93 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -21,6 +21,7 @@ remove/1, remove/2, md5sum/1, + sha1sum/1, read/1, write/2, write_term/2 @@ -90,6 +91,12 @@ copy(From, To) -> -spec md5sum(string() | binary()) -> string(). md5sum(Value) -> hex(binary_to_list(erlang:md5(Value))). + +%% @doc return an sha1sum checksum string or a binary. Same as unix utility of +%% same name. +-spec sha1sum(string() | binary()) -> string(). +sha1sum(Value) -> + hex(binary_to_list(crypto:hash(sha, Value))). %% @doc delete a file. Use the recursive option for directories. %%
@@ -312,6 +319,9 @@ setup_test() ->
 
 md5sum_test() ->
     ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")).
+    
+sha1sum_test() ->
+    ?assertMatch("b6589fc6ab0dc82cf12099d1c2d40ab994e8410c", sha1sum("0")).
 
 file_test() ->
     Dir = insecure_mkdtemp(),

From 3121c892b4fdeec4f6ccc38c764f80d27591ee4b Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Sat, 24 May 2014 09:42:57 -0500
Subject: [PATCH 104/240] support r14/15 crypto

---
 rebar.config    | 1 +
 src/ec_file.erl | 8 +++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/rebar.config b/rebar.config
index 07a123c..3cd89c7 100644
--- a/rebar.config
+++ b/rebar.config
@@ -10,6 +10,7 @@
 %% Compiler Options ============================================================
 {erl_opts,
  [{platform_define, "^[0-9]+", namespaced_types},
+  {platform_define, "^R1[4|5]", deprecated_crypto},
   debug_info,
   warnings_as_errors]}.
 
diff --git a/src/ec_file.erl b/src/ec_file.erl
index 3fe8a93..1885bde 100644
--- a/src/ec_file.erl
+++ b/src/ec_file.erl
@@ -94,9 +94,15 @@ md5sum(Value) ->
     
 %% @doc return an sha1sum checksum string or a binary. Same as unix utility of
 %%      same name.
+-ifdef(deprecated_crypto).
 -spec sha1sum(string() | binary()) -> string().
-sha1sum(Value) ->
+sha1sum(Value) ->  
+    hex(binary_to_list(crypto:sha(Value))).
+-else.
+-spec sha1sum(string() | binary()) -> string().
+sha1sum(Value) ->  
     hex(binary_to_list(crypto:hash(sha, Value))).
+-endif.
 
 %% @doc delete a file. Use the recursive option for directories.
 %% 

From 7a32f52e7d417d1618e95c36062db5727d964371 Mon Sep 17 00:00:00 2001
From: Jamie Winsor 
Date: Wed, 9 Jul 2014 13:24:10 -0700
Subject: [PATCH 105/240] add ec_file:is_dir/1

use ec_file:is_dir/1 to identify symlinks which are directories
Ensure contents of symlinked directories are copied when using ec_file:copy/3
---
 src/ec_file.erl | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/src/ec_file.erl b/src/ec_file.erl
index 1885bde..05563fc 100644
--- a/src/ec_file.erl
+++ b/src/ec_file.erl
@@ -16,6 +16,7 @@
          mkdir_p/1,
          find/2,
          is_symlink/1,
+         is_dir/1,
          type/1,
          real_dir_path/1,
          remove/1,
@@ -58,7 +59,7 @@ exists(Filename) ->
 copy(From, To, []) ->
     copy(From, To);
 copy(From, To, [recursive] = Options) ->
-    case filelib:is_dir(From) of
+    case is_dir(From) of
         false ->
             copy(From, To);
         true ->
@@ -130,6 +131,15 @@ is_symlink(Path) ->
         _ ->
             false
     end.
+
+is_dir(Path) ->
+    case file:read_file_info(Path) of
+        {ok, #file_info{type = directory}} ->
+            true;
+        _ ->
+            false
+    end.
+
 %% @doc returns the type of the file.
 -spec type(file:name()) -> file | symlink | directory | undefined.
 type(Path) ->
@@ -139,11 +149,12 @@ type(Path) ->
         false ->
             case is_symlink(Path) of
                 true ->
-                    symlink;  
-                false -> case filelib:is_dir(Path) of
-                             true -> directory;
-                             false -> undefined
-                         end
+                    symlink;
+                false ->
+                    case is_dir(Path) of
+                        true -> directory;
+                        false -> undefined
+                    end
             end
 
     end.
@@ -218,7 +229,7 @@ write_term(FileName, Term) ->
 find([], _) ->
     [];
 find(FromDir, TargetPattern) ->
-    case filelib:is_dir(FromDir) of
+    case is_dir(FromDir) of
         false ->
             case re:run(FromDir, TargetPattern) of
                 {match, _} -> [FromDir];
@@ -253,7 +264,7 @@ find_in_subdirs(FromDir, TargetPattern) ->
 
 -spec remove_recursive(file:name(), Options::list()) -> ok | {error, Reason::term()}.
 remove_recursive(Path, Options) ->
-    case filelib:is_dir(Path) of
+    case is_dir(Path) of
         false ->
             file:delete(Path);
         true ->
@@ -284,7 +295,7 @@ copy_subfiles(From, To, Options) ->
 
 -spec make_dir_if_dir(file:name()) -> ok | {error, Reason::term()}.
 make_dir_if_dir(File) ->
-    case filelib:is_dir(File) of
+    case is_dir(File) of
         true  -> ok;
         false -> mkdir_path(File)
     end.

From c25dce9689cb242b7a477632b35f5606e6e72e7a Mon Sep 17 00:00:00 2001
From: Jean Rouge 
Date: Fri, 12 Sep 2014 12:25:27 -0700
Subject: [PATCH 106/240] Adding an `ec_test:format_iso8601/1` fun to format
 datetimes according to ISO8601 standards

And added a couple unit tests on it.
---
 src/ec_date.erl | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/ec_date.erl b/src/ec_date.erl
index 73eb15d..6941a2f 100644
--- a/src/ec_date.erl
+++ b/src/ec_date.erl
@@ -25,6 +25,7 @@
 -author("Dale Harvey ").
 
 -export([format/1, format/2]).
+-export([format_iso8601/1]).
 -export([parse/1, parse/2]).
 -export([nparse/1]).
 
@@ -42,6 +43,8 @@
 -define( is_month(X), ( (is_integer(X) andalso X =< 12) orelse ?is_hinted_month(X) ) ).
 
 -define(GREGORIAN_SECONDS_1970, 62167219200).
+-define(ISO_8601_DATETIME_FORMAT, "Y-m-dTG:i:sZ").
+-define(ISO_8601_DATETIME_WITH_MS_FORMAT, "Y-m-dTG:i:s.fZ").
 
 -type year() :: non_neg_integer().
 -type month() :: 1..12 | {?MONTH_TAG, 1..12}.
@@ -74,6 +77,14 @@ format(Format, {_,_,Ms}=Now) ->
 format(Format, Date) ->
     format(Format, Date, []).
 
+-spec format_iso8601(datetime()) -> string().
+%% @doc format date in the ISO8601 format
+%% This always puts 'Z' as time zone, since we have no notion of timezone
+format_iso8601({{_, _, _}, {_, _, _}} = Date) ->
+    format(?ISO_8601_DATETIME_FORMAT, Date);
+format_iso8601({{_, _, _}, {_, _, _, _}} = Date) ->
+    format(?ISO_8601_DATETIME_WITH_MS_FORMAT, Date).
+
 -spec parse(string()) -> datetime().
 %% @doc parses the datetime from a string
 parse(Date) ->
@@ -938,4 +949,11 @@ zulu_test_() ->
      ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04:00")),
                    "2001-03-10T19:16:17")
     ].
+
+format_iso8601_test_() ->
+    [
+     ?_assertEqual("2001-03-10T17:16:17Z", format_iso8601(?DATE)),
+     ?_assertEqual("2001-03-10T17:16:17.123456Z", format_iso8601(?DATEMS))
+    ].
+
 -endif.

From 4fb4199da3fd62119af3954fb2062bd020db365b Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Sat, 27 Sep 2014 14:06:49 -0500
Subject: [PATCH 107/240] fix error log message being colored green instead of
 red

---
 src/ec_cmd_log.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl
index e61e67a..479b242 100644
--- a/src/ec_cmd_log.erl
+++ b/src/ec_cmd_log.erl
@@ -149,7 +149,7 @@ error(LogState, String) ->
 %% and argements @see io:format/2
 -spec error(t(), string(), [any()]) -> ok.
 error(LogState, FormatString, Args) ->
-    log(LogState, ?EC_ERROR, colorize(LogState, ?GREEN, false, FormatString), Args).
+    log(LogState, ?EC_ERROR, colorize(LogState, ?RED, false, FormatString), Args).
 
 %% @doc log at the warn level given the current log state with a string or
 %% format string that returns a function

From 0b47f60bfbb8f47ba67665991ba0bb0c949ff0b0 Mon Sep 17 00:00:00 2001
From: Jean Rouge 
Date: Wed, 1 Oct 2014 12:31:47 -0700
Subject: [PATCH 108/240] Have dialyzer run on Travis for OTP 17 too

v17 does not have the leading 'R'
```
erl -noshell -eval 'io:format("~p", [erlang:system_info(otp_release)]), erlang:halt(0).'
"17"
```
So the dialyzer wouldn't run in the Travis builds.

And a minor spec fix to appease v17's dialyzer.
---
 Makefile            |  2 +-
 src/ec_gb_trees.erl | 41 ++++++++++++++---------------------------
 2 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/Makefile b/Makefile
index 0269ee8..de0f3e7 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ endif
 # dialyzer on R15 and above. However on R14 and below we have the
 # problem that travis times out. The code below lets us not run
 # dialyzer on R14
-OTP_VSN=$(shell erl -noshell -eval 'io:format("~p", [erlang:system_info(otp_release)]), erlang:halt(0).' | perl -lne 'print for /R(\d+).*/g')
+OTP_VSN=$(shell erl -noshell -eval '{match, [Major]} = re:run(erlang:system_info(otp_release), "^R?([0-9]+).*", [{capture, all_but_first, list}]), io:format("~p", [Major]), erlang:halt(0).')
 TRAVIS_SLOW=$(shell expr $(OTP_VSN) \<= 15 )
 
 ifeq ($(TRAVIS_SLOW), 0)
diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl
index 50d9701..a87ab86 100644
--- a/src/ec_gb_trees.erl
+++ b/src/ec_gb_trees.erl
@@ -26,19 +26,6 @@
          from_list/1,
          keys/1]).
 
--export_type([dictionary/2]).
-
-%%%===================================================================
-%%% Types
-%%%===================================================================
-%% This should be opaque, but that kills dialyzer so for now we export it
-%% however you should not rely on the internal representation here
--type dictionary(K, V) :: {non_neg_integer(), ec_gb_tree_node(K, V)}.
-
--type ec_gb_tree_node(K, V) :: 'nil' | {K, V,
-                                        ec_gb_tree_node(K, V),
-                                        ec_gb_tree_node(K, V)}.
-
 %%%===================================================================
 %%% API
 %%%===================================================================
@@ -49,7 +36,7 @@
 %% same implementation is created and returned.
 %%
 %% @param ModuleName|Object The module name or existing dictionary object.
--spec new() -> dictionary(_K, _V).
+-spec new() -> gb_trees:tree(_K, _V).
 new() ->
     gb_trees:empty().
 
@@ -57,7 +44,7 @@ new() ->
 %%
 %% @param Object The dictory object to check
 %% @param Key The key to check the dictionary for
--spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean().
+-spec has_key(ec_dictionary:key(K), Object::gb_trees:tree(K, _V)) -> boolean().
 has_key(Key, Data) ->
     case gb_trees:lookup(Key, Data) of
         {value, _Val} ->
@@ -72,7 +59,7 @@ has_key(Key, Data) ->
 %% @param Object The dictionary object to return the value from
 %% @param Key The key requested
 %% when the key does not exist @throws not_found
--spec get(ec_dictionary:key(K), Object::dictionary(K, V)) ->
+-spec get(ec_dictionary:key(K), Object::gb_trees:tree(K, V)) ->
     ec_dictionary:value(V).
 get(Key, Data) ->
     case gb_trees:lookup(Key, Data) of
@@ -84,7 +71,7 @@ get(Key, Data) ->
 
 -spec get(ec_dictionary:key(K),
           ec_dictionary:value(V),
-          Object::dictionary(K, V)) ->
+          Object::gb_trees:tree(K, V)) ->
     ec_dictionary:value(V).
 get(Key, Default, Data) ->
     case gb_trees:lookup(Key, Data) of
@@ -101,8 +88,8 @@ get(Key, Default, Data) ->
 %% @param Key the key to add
 %% @param Value the value to add
 -spec add(ec_dictionary:key(K), ec_dictionary:value(V),
-          Object::dictionary(K, V)) ->
-    dictionary(K, V).
+          Object::gb_trees:tree(K, V)) ->
+    gb_trees:tree(K, V).
 add(Key, Value, Data) ->
     gb_trees:enter(Key, Value, Data).
 
@@ -111,8 +98,8 @@ add(Key, Value, Data) ->
 %%
 %% @param Object the dictionary object to remove the value from
 %% @param Key the key of the key/value pair to remove
--spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) ->
-    dictionary(K, V).
+-spec remove(ec_dictionary:key(K), Object::gb_trees:tree(K, V)) ->
+    gb_trees:tree(K, V).
 remove(Key, Data) ->
     gb_trees:delete_any(Key, Data).
 
@@ -120,24 +107,24 @@ remove(Key, Data) ->
 %%
 %% @param Object the dictionary object to check
 %% @param Value The value to check if exists
--spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean().
+-spec has_value(ec_dictionary:value(V), Object::gb_trees:tree(_K, V)) -> boolean().
 has_value(Value, Data) ->
     lists:member(Value, gb_trees:values(Data)).
 
 %% @doc return the current number of key value pairs in the dictionary
 %%
 %% @param Object the object return the size for.
--spec size(Object::dictionary(_K, _V)) -> non_neg_integer().
+-spec size(Object::gb_trees:tree(_K, _V)) -> non_neg_integer().
 size(Data) ->
     gb_trees:size(Data).
 
--spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K),
-                                     ec_dictionary:value(V)}].
+-spec to_list(gb_trees:tree(K, V)) -> [{ec_dictionary:key(K),
+                                        ec_dictionary:value(V)}].
 to_list(Data) ->
     gb_trees:to_list(Data).
 
 -spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) ->
-    dictionary(K, V).
+    gb_trees:tree(K, V).
 from_list(List) when is_list(List) ->
     lists:foldl(fun({Key, Value}, Dict) ->
                         gb_trees:enter(Key, Value, Dict)
@@ -145,7 +132,7 @@ from_list(List) when is_list(List) ->
                 gb_trees:empty(),
                 List).
 
--spec keys(dictionary(K,_V)) -> [ec_dictionary:key(K)].
+-spec keys(gb_trees:tree(K,_V)) -> [ec_dictionary:key(K)].
 keys(Data) ->
     gb_trees:keys(Data).
 

From 5ef8371020b824b8cfad3bcaf6d60ecb575d5e3e Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Mon, 3 Nov 2014 11:55:06 -0600
Subject: [PATCH 109/240] make git vsn the same as used in rebar_vsn_plugin

---
 src/ec_git_vsn.erl | 81 ++++++++++++++++++++++++++++------------------
 1 file changed, 49 insertions(+), 32 deletions(-)

diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl
index f06ea8e..680b194 100644
--- a/src/ec_git_vsn.erl
+++ b/src/ec_git_vsn.erl
@@ -36,44 +36,61 @@ new() ->
 
 -spec vsn(t()) -> {ok, string()} | {error, Reason::any()}.
 vsn(_Data) ->
-    Result = do_cmd("git describe --tags --always"),
-    case re:split(Result, "-") of
-        [Vsn, Count, RefTag] ->
-            erlang:iolist_to_binary([strip_leading_v(Vsn),
-                                     <<"+build.">>,
-                                     Count,
-                                     <<".ref.">>,
-                                     RefTag]);
-        [VsnOrRefTag] ->
-            case re:run(VsnOrRefTag, "^[0-9a-fA-F]+$") of
-                {match, _} ->
-                    find_vsn_from_start_of_branch(VsnOrRefTag);
-                nomatch ->
-                    strip_leading_v(VsnOrRefTag)
-            end;
-        _ ->
-            {error, {invalid_result, Result}}
-    end.
+    {Vsn, RawRef, RawCount} = collect_default_refcount(),
+    {ok, build_vsn_string(Vsn, RawRef, RawCount)}.
 
 %%%===================================================================
 %%% Internal Functions
 %%%===================================================================
--spec strip_leading_v(string()) -> string().
-strip_leading_v(Vsn) ->
-    case re:run(Vsn, "v?(.+)", [{capture, [1], binary}]) of
-        {match, [NVsn]} ->
-            NVsn;
+
+collect_default_refcount() ->
+    %% Get the tag timestamp and minimal ref from the system. The
+    %% timestamp is really important from an ordering perspective.
+    RawRef = os:cmd("git log -n 1 --pretty=format:'%h\n' "),
+
+    {Tag, TagVsn} = parse_tags(),
+    RawCount =
+        case Tag of
+            undefined ->
+                os:cmd("git rev-list HEAD | wc -l");
+            _ ->
+                get_patch_count(Tag)
+        end,
+    {TagVsn, RawRef, RawCount}.
+
+build_vsn_string(Vsn, RawRef, RawCount) ->
+    %% Cleanup the tag and the Ref information. Basically leading 'v's and
+    %% whitespace needs to go away.
+    RefTag = case RawRef of
+                 undefined ->
+                     "";
+                 RawRef ->
+                     [".ref", re:replace(RawRef, "\\s", "", [global])]
+             end,
+    Count = erlang:iolist_to_binary(re:replace(RawCount, "\\s", "", [global])),
+
+    %% Create the valid [semver](http://semver.org) version from the tag
+    case Count of
+        <<"0">> ->
+            erlang:binary_to_list(erlang:iolist_to_binary(Vsn));
         _ ->
-            Vsn
+            erlang:binary_to_list(erlang:iolist_to_binary([Vsn, "+build.",
+                                                           Count, RefTag]))
     end.
 
--spec find_vsn_from_start_of_branch(string()) -> string().
-find_vsn_from_start_of_branch(RefTag) ->
-    Count = do_cmd("git rev-list HEAD --count"),
-    erlang:iolist_to_binary(["0.0.0+build.", Count, ".ref.", RefTag]).
+get_patch_count(RawRef) ->
+    Ref = re:replace(RawRef, "\\s", "", [global]),
+    Cmd = io_lib:format("git rev-list ~s..HEAD | wc -l",
+                         [Ref]),
+    os:cmd(Cmd).
 
-do_cmd(Cmd) ->
-    trim_whitespace(os:cmd(Cmd)).
+parse_tags() ->
+    first_valid_tag(os:cmd("git log --oneline --decorate  | fgrep \"tag: \" -1000")).
 
-trim_whitespace(Input) ->
-     re:replace(Input, "\\s+", "", [global]).
+first_valid_tag(Line) ->
+    case re:run(Line, "(\\(|\\s)tag:\\s(v([^,\\)]+))", [{capture, [2, 3], list}]) of
+        {match,[Tag, Vsn]} ->
+            {Tag, Vsn};
+        nomatch ->
+            {undefined, "0.0.0"}
+    end.

From 441d11820d8a3983bbfec955a3abcf2e3df9b3bc Mon Sep 17 00:00:00 2001
From: Brian Lee Yung Rowe 
Date: Tue, 2 Dec 2014 17:04:08 -0500
Subject: [PATCH 110/240] Parse Twitter-style dates

---
 src/ec_date.erl          | 15 ++++++++++++++-
 src/ec_semver_parser.erl |  2 +-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/ec_date.erl b/src/ec_date.erl
index 6941a2f..177230c 100644
--- a/src/ec_date.erl
+++ b/src/ec_date.erl
@@ -28,6 +28,7 @@
 -export([format_iso8601/1]).
 -export([parse/1, parse/2]).
 -export([nparse/1]).
+-export([tokenise/2]).
 
 %% These are used exclusively as guards and so the function like
 %% defines make sense
@@ -41,6 +42,7 @@
 -define( is_day(X), (is_integer(X) andalso X =< 31) ).
 -define( is_hinted_month(X), (is_tuple(X) andalso size(X)=:=2 andalso element(1,X)=:=?MONTH_TAG) ).
 -define( is_month(X), ( (is_integer(X) andalso X =< 12) orelse ?is_hinted_month(X) ) ).
+-define( is_tz_offset(H1,H2,M1,M2), (?is_num(H1) andalso ?is_num(H2) andalso ?is_num(M1) andalso ?is_num(M2)) ).
 
 -define(GREGORIAN_SECONDS_1970, 62167219200).
 -define(ISO_8601_DATETIME_FORMAT, "Y-m-dTG:i:sZ").
@@ -207,6 +209,11 @@ parse([Month,Day,Year,Hour,$:,Min], _Now, _Opts)
   when ?is_hinted_month(Month) andalso ?is_day(Day) ->
     {{Year, Month, Day}, {hour(Hour, []), Min, 0}};
 
+%% Date/Times Fri Nov 21 14:55:26 +0000 2014 (Twitter format)
+parse([Month, Day, Hour,$:,Min,$:,Sec, Year], _Now, _Opts)
+  when ?is_hinted_month(Month), ?is_day(Day), ?is_year(Year) ->
+    {{Year, Month, Day}, {hour(Hour, []), Min, Sec}};
+
 %% Times - 21:45, 13:45:54, 13:15PM etc
 parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) ->
     {Date, {hour(Hour, PAM), Min, Sec}};
@@ -399,6 +406,7 @@ tokenise("OF"++Rest, Acc) -> tokenise(Rest, Acc);
 tokenise("T"++Rest, Acc) -> tokenise(Rest, Acc);  % 2012-12-12T12:12:12 ISO formatting.
 tokenise([$Z | Rest], Acc) -> tokenise(Rest, [$Z | Acc]);  % 2012-12-12T12:12:12Zulu
 tokenise([$. |  Rest], Acc) -> tokenise(Rest, [$. | Acc]);  % 2012-12-12T12:12:12.xxxx ISO formatting.
+tokenise([$+, H1,H2,M1,M2| Rest], Acc) when ?is_tz_offset(H1,H2,M1,M2) -> tokenise(Rest, Acc);  % Tue Nov 11 15:03:18 +0000 2014 Twitter format
 tokenise([$+| Rest], Acc) -> tokenise(Rest, [$+ | Acc]);  % 2012-12-12T12:12:12.xxxx+ ISO formatting.
 
 tokenise([Else | Rest], Acc) ->
@@ -888,7 +896,12 @@ parse_with_days_test_() ->
      ?_assertEqual({{2008,8,22}, {6,0,0}},
                    parse("Monday 22 Aug 2008 6a", ?DATE)),
      ?_assertEqual({{2008,8,22}, {18,35,0}},
-                   parse("Mon, 22 Aug 2008 6:35 PM", ?DATE))
+                   parse("Mon, 22 Aug 2008 6:35 PM", ?DATE)),
+     % Twitter style
+     ?_assertEqual({{2008,8,22}, {06,35,04}},
+                   parse("Mon Aug 22 06:35:04 +0000 2008", ?DATE)),
+     ?_assertEqual({{2008,8,22}, {06,35,04}},
+                   parse("Mon Aug 22 06:35:04 +0500 2008", ?DATE))
     ].
 
 parse_with_TZ_test_() ->
diff --git a/src/ec_semver_parser.erl b/src/ec_semver_parser.erl
index 7aeeec1..dfd9eda 100644
--- a/src/ec_semver_parser.erl
+++ b/src/ec_semver_parser.erl
@@ -17,7 +17,7 @@
 file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -> Err end.
 
 -spec parse(binary() | list()) -> any().
-parse(List) when is_list(List) -> parse(list_to_binary(List));
+parse(List) when is_list(List) -> parse(unicode:characters_to_binary(List));
 parse(Input) when is_binary(Input) ->
   _ = setup_memo(),
   Result = case 'semver'(Input,{{line,1},{column,1}}) of

From 6079300634eeb0a5ec9356d8c3032ca0d88c5836 Mon Sep 17 00:00:00 2001
From: Jesper Louis Andersen 
Date: Wed, 11 Feb 2015 17:05:33 +0100
Subject: [PATCH 111/240] Refactor: fold colorize_/3 into colorize/4.

Fold a local one-line leaf function with exactly one call-site into its caller.
---
 src/ec_cmd_log.erl | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl
index 479b242..5bbd7fa 100644
--- a/src/ec_cmd_log.erl
+++ b/src/ec_cmd_log.erl
@@ -218,14 +218,10 @@ format(Log) ->
 
 -spec colorize(t(), color(), boolean(), string()) -> string().
 colorize(#state_t{caller=command_line}, Color, false, Msg) when is_integer(Color) ->
-    colorize_(Color, 0, Msg);
+    lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [0, Color, ?PREFIX, Msg]));
 colorize(_LogState, _Color, _Bold, Msg) ->
     Msg.
 
--spec colorize_(color(), integer(), string()) -> string().
-colorize_(Color, Bold, Msg) when is_integer(Color), is_integer(Bold)->
-    lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [Bold, Color, ?PREFIX, Msg])).
-
 %%%===================================================================
 %%% Test Functions
 %%%===================================================================

From aa373dddbee868a4628e10a28736c71d98fa5c1f Mon Sep 17 00:00:00 2001
From: Jesper Louis Andersen 
Date: Sun, 8 Feb 2015 16:05:39 +0100
Subject: [PATCH 112/240] Introduce simple, preliminary TERM capability query.

When erlware_commons logs to the command_line, it assumes the
environment has common modern capabilities and color display. In
general, this is not the case and then color codes are sent verbatim
to the terminal.

This patch introduces a new field in #state_t{}, term_cap, encoding
if the terminal runs with 'full' or 'dumb' capabilities. In the latter case,
color display is suppressed. Initialization of the #state_t{} record queries
the environment once for the TERM variable in order to figure out what
it supports. The default is 'full' capability to be fully backwards compatible.
---
 src/ec_cmd_log.erl | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl
index 5bbd7fa..8d528f0 100644
--- a/src/ec_cmd_log.erl
+++ b/src/ec_cmd_log.erl
@@ -50,7 +50,8 @@
 -define(PREFIX, "===> ").
 
 -record(state_t, {log_level=0 :: int_log_level(),
-                  caller=api :: caller()}).
+                  caller=api :: caller(),
+                  term_cap=full :: full | dumb }).
 
 %%============================================================================
 %% types
@@ -86,7 +87,7 @@ new(LogLevel) ->
 
 -spec new(log_level(), caller()) -> t().
 new(LogLevel, Caller) when LogLevel >= 0, LogLevel =< 3 ->
-    #state_t{log_level=LogLevel, caller=Caller};
+    #state_t{log_level=LogLevel, caller=Caller, term_cap=query_term_env()};
 new(AtomLogLevel, Caller)
   when AtomLogLevel =:= error;
        AtomLogLevel =:= warn;
@@ -217,11 +218,27 @@ format(Log) ->
      <<")">>].
 
 -spec colorize(t(), color(), boolean(), string()) -> string().
-colorize(#state_t{caller=command_line}, Color, false, Msg) when is_integer(Color) ->
+colorize(#state_t{caller=command_line, term_cap=full}, Color, false, Msg) when is_integer(Color) ->
     lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [0, Color, ?PREFIX, Msg]));
+colorize(#state_t{caller=command_line, term_cap=dumb}, Color, _Bold, Msg) when is_integer(Color) ->
+    lists:flatten(io_lib:format("~s~s", [?PREFIX, Msg]));
 colorize(_LogState, _Color, _Bold, Msg) ->
     Msg.
 
+%% @doc Query the term enviroment
+%% For reasons of simplicity, we don't parse terminal capabilities yet, although
+%% a later version could do so. Rather, we provide a simple match-list of terminal
+%% capabilities.
+%% @end
+-spec query_term_env() -> full | dumb.
+query_term_env() ->
+    term_capabilities(os:getenv("TERM")).
+
+-spec term_capabilities(string()) -> full | dumb.
+term_capabilities("xterm") -> full;
+term_capabilities("dumb") -> dumb;
+term_capabilities(_) -> full. %% Default to the backwards compatible version.
+
 %%%===================================================================
 %%% Test Functions
 %%%===================================================================

From e07d08333a5887d67dbf104f7cb156ee02f4777f Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Thu, 23 Apr 2015 17:49:34 -0500
Subject: [PATCH 113/240] use #atom{} syntax to support 18

---
 src/ec_cmd_log.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl
index 479b242..1bd3961 100644
--- a/src/ec_cmd_log.erl
+++ b/src/ec_cmd_log.erl
@@ -74,7 +74,7 @@
 
 -type color() :: 31..36.
 
--opaque t() :: record(state_t).
+-opaque t() :: #state_t{}.
 
 %%============================================================================
 %% API

From 7015ba29512cd76a5781850482c49702405957f2 Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Thu, 23 Apr 2015 17:56:56 -0500
Subject: [PATCH 114/240] remove use of deprecated function erlang:now/0

---
 src/ec_date.erl |  2 +-
 src/ec_file.erl | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/ec_date.erl b/src/ec_date.erl
index 73eb15d..b71d134 100644
--- a/src/ec_date.erl
+++ b/src/ec_date.erl
@@ -907,7 +907,7 @@ iso_test_() ->
     ].
 
 ms_test_() ->
-    Now=now(),
+    Now=os:timestamp(),
     [
      ?_assertEqual({{2012,12,12}, {12,12,12,1234}}, parse("2012-12-12T12:12:12.1234")),
      ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS),
diff --git a/src/ec_file.erl b/src/ec_file.erl
index 05563fc..e283c64 100644
--- a/src/ec_file.erl
+++ b/src/ec_file.erl
@@ -92,16 +92,16 @@ copy(From, To) ->
 -spec md5sum(string() | binary()) -> string().
 md5sum(Value) ->
     hex(binary_to_list(erlang:md5(Value))).
-    
+
 %% @doc return an sha1sum checksum string or a binary. Same as unix utility of
 %%      same name.
 -ifdef(deprecated_crypto).
 -spec sha1sum(string() | binary()) -> string().
-sha1sum(Value) ->  
+sha1sum(Value) ->
     hex(binary_to_list(crypto:sha(Value))).
 -else.
 -spec sha1sum(string() | binary()) -> string().
-sha1sum(Value) ->  
+sha1sum(Value) ->
     hex(binary_to_list(crypto:hash(sha, Value))).
 -endif.
 
@@ -174,7 +174,7 @@ real_dir_path(Path) ->
 %% function of the same name.
 -spec insecure_mkdtemp() -> TmpDirPath::file:name().
 insecure_mkdtemp() ->
-    random:seed(now()),
+    random:seed(os:timestamp()),
     UniqueNumber = erlang:integer_to_list(erlang:trunc(random:uniform() * 1000000000000)),
     TmpDirPath =
         filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]),
@@ -336,7 +336,7 @@ setup_test() ->
 
 md5sum_test() ->
     ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")).
-    
+
 sha1sum_test() ->
     ?assertMatch("b6589fc6ab0dc82cf12099d1c2d40ab994e8410c", sha1sum("0")).
 

From 4c20e1903d928865a01ac316024fa33f8ab61255 Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Sun, 31 May 2015 12:04:54 -0500
Subject: [PATCH 115/240] fix conversion of ask/2 string

---
 src/ec_talk.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ec_talk.erl b/src/ec_talk.erl
index 243f7b4..5e24f2c 100644
--- a/src/ec_talk.erl
+++ b/src/ec_talk.erl
@@ -83,7 +83,7 @@ ask(Prompt, boolean) ->
 ask(Prompt, number) ->
     ask_convert(Prompt, fun get_integer/1, number,  none);
 ask(Prompt, string) ->
-    ask_convert(Prompt, fun get_integer/1, string, none).
+    ask_convert(Prompt, fun get_string/1, string, none).
 
 %% @doc Asks the user to respond to the prompt. Trys to return the
 %% value in the format specified by 'Type'.

From d726ba274221aaf509341d2df21d5bbed4bee992 Mon Sep 17 00:00:00 2001
From: Tristan Sloughter 
Date: Mon, 22 Jun 2015 12:17:01 -0500
Subject: [PATCH 116/240] move to rebar3 and bump version

---
 .travis.yml                 |   7 +--
 Makefile                    | 119 ------------------------------------
 rebar.config                |  13 ++--
 rebar.config.script         |  42 -------------
 rebar.lock                  |   1 +
 rebar3                      | Bin 0 -> 352647 bytes
 src/erlware_commons.app.src |  10 ++-
 7 files changed, 18 insertions(+), 174 deletions(-)
 delete mode 100644 Makefile
 delete mode 100644 rebar.config.script
 create mode 100644 rebar.lock
 create mode 100755 rebar3

diff --git a/.travis.yml b/.travis.yml
index bf58212..fcb6c23 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,12 +7,7 @@ otp_release:
        - R16B01
        - R16B
        - R15B02
-       - R15B01
-       - R15B
-       - R14B04
-       - R14B03
-       - R14B02
-script: "make rebuild"
+script: "./rebar3 compile && ./rebar3 ct"
 branches:
         only:
                 - master
diff --git a/Makefile b/Makefile
deleted file mode 100644
index de0f3e7..0000000
--- a/Makefile
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2012 Erlware, LLC. All Rights Reserved.
-#
-# BSD License see COPYING
-
-ERL = $(shell which erl)
-ERL_VER = $(shell erl -eval 'io:format("~s", [erlang:system_info(otp_release)]), halt().'  -noshell)
-ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt
-
-ERLFLAGS= -pa $(CURDIR)/.eunit -pa $(CURDIR)/ebin -pa $(CURDIR)/*/ebin
-
-# =============================================================================
-# Verify that the programs we need to run are installed on this system
-# =============================================================================
-
-REBAR ?= $(shell which rebar)
-
-ifeq ($(REBAR),)
-$(error "Rebar not available on this system")
-endif
-
-# =============================================================================
-# Handle version discovery
-# =============================================================================
-
-# We have a problem that we only have 10 minutes to build on travis
-# and those travis boxes are quite small. This is ok for the fast
-# dialyzer on R15 and above. However on R14 and below we have the
-# problem that travis times out. The code below lets us not run
-# dialyzer on R14
-OTP_VSN=$(shell erl -noshell -eval '{match, [Major]} = re:run(erlang:system_info(otp_release), "^R?([0-9]+).*", [{capture, all_but_first, list}]), io:format("~p", [Major]), erlang:halt(0).')
-TRAVIS_SLOW=$(shell expr $(OTP_VSN) \<= 15 )
-
-ifeq ($(TRAVIS_SLOW), 0)
-DIALYZER=$(shell which dialyzer)
-else
-DIALYZER=: not running dialyzer on R14 or R15
-endif
-
-# =============================================================================
-# Rules to build the system
-# =============================================================================
-
-.PHONY: all compile doc clean test shell distclean pdf get-deps rebuild dialyzer typer
-
-all: compile doc test
-
-rebuild: distclean deps compile dialyzer test
-
-deps: .DEV_MODE
-	$(REBAR) get-deps compile
-
-.DEV_MODE:
-	touch $@
-	cp priv/ec_semver_parser.peg src
-
-get-deps:
-	$(REBAR) get-deps compile
-
-compile: deps
-	$(REBAR) skip_deps=true compile
-
-
-doc: compile
-	- $(REBAR) skip_deps=true doc
-
-test: compile
-	$(REBAR) skip_deps=true eunit
-
-$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts:
-	@echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base
-	@echo
-
-	- $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).erts --build_plt \
-	   --apps erts
-
-$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel:$(ERLWARE_COMMONS_PLT).$(ERL_VER).erts
-	@echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base
-	@echo
-	- $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel --build_plt \
-	   --apps kernel
-
-$(ERLWARE_COMMONS_PLT).$(ERL_VER).base:$(ERLWARE_COMMONS_PLT).$(ERL_VER).kernel
-	@echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER).base
-	@echo
-	- $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base --build_plt \
-	   --apps stdlib
-
-$(ERLWARE_COMMONS_PLT).$(ERL_VER): $(ERLWARE_COMMONS_PLT).$(ERL_VER).base
-	@echo Building local plt at $(ERLWARE_COMMONS_PLT).$(ERL_VER)
-	@echo
-	- $(DIALYZER) --fullpath --verbose --output_plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) --add_to_plt --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER).base \
-	   --apps eunit -r deps
-
-dialyzer: compile $(ERLWARE_COMMONS_PLT).$(ERL_VER)
-	$(DIALYZER) --fullpath --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -Wrace_conditions -r ./ebin
-
-typer: $(ERLWARE_COMMONS_PLT).$(ERL_VER)
-	typer --plt $(ERLWARE_COMMONS_PLT).$(ERL_VER) -r ./src
-
-shell: compile
-# You often want *rebuilt* rebar tests to be available to the
-# shell you have to call eunit (to get the tests
-# rebuilt). However, eunit runs the tests, which probably
-# fails (thats probably why You want them in the shell). This
-# runs eunit but tells make to ignore the result.
-	- @$(REBAR) skip_deps=true eunit
-	@$(ERL) $(ERLFLAGS)
-
-clean:
-	$(REBAR) skip_deps=true clean
-	- rm $(CURDIR)/doc/*.html
-	- rm $(CURDIR)/doc/*.css
-	- rm $(CURDIR)/doc/*.png
-	- rm $(CURDIR)/doc/edoc-info
-
-distclean: clean
-	rm -rf $(ERLWARE_COMMONS_PLT).$(ERL_VER)
-	rm -rvf $(CURDIR)/deps
-	rm -rvf .DEV_MODE
diff --git a/rebar.config b/rebar.config
index 3cd89c7..48d5b07 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,15 +1,14 @@
 %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*-
 
 %% Dependencies ================================================================
-{deps, [{rebar_vsn_plugin, ".*",
-         {git, "https://github.com/erlware/rebar_vsn_plugin.git",
-          {branch, "master"}}}]}.
+{deps, []}.
 
 {erl_first_files, ["ec_dictionary", "ec_vsn"]}.
 
 %% Compiler Options ============================================================
 {erl_opts,
  [{platform_define, "^[0-9]+", namespaced_types},
+  {platform_define, "^[0-9]+", have_callback_support},
   {platform_define, "^R1[4|5]", deprecated_crypto},
   debug_info,
   warnings_as_errors]}.
@@ -21,5 +20,9 @@
 {cover_enabled, true}.
 {cover_print_enabled, true}.
 
-%% Rebar Plugins ==============================================================
-{plugins, [rebar_vsn_plugin]}.
+%% Profiles ====================================================================
+{profiles, [{dev, [{deps, [{neotoma, "",
+                            {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}},
+                           {proper, "",
+                            {git, "https://github.com/bkearns/proper.git", {branch, master}}}]}]}
+           ]}.
diff --git a/rebar.config.script b/rebar.config.script
deleted file mode 100644
index 6519616..0000000
--- a/rebar.config.script
+++ /dev/null
@@ -1,42 +0,0 @@
-%% Merge the list values in `ToAdd' into the list found at key `Key'
-%% in proplist `C'. Don't duplicate items. New Items are added to the
-%% front of existing items. It is an error if the value at `Key' is
-%% not a list in `C'.
-MergeConfig = fun({Key, ToAdd}, C) ->
-                      case lists:keyfind(Key, 1, C) of
-                          false ->
-                              lists:keystore(Key, 1, C, {Key, ToAdd});
-                          {Key, List} when is_list(List) ->
-                              %% remove items in ToAdd already in List
-                              ToAdd1 = [ I || I <- ToAdd, not lists:member(I, List) ],
-                              lists:keystore(Key, 1, C, {Key, ToAdd1 ++ List })
-                      end
-              end.
-
-{match, [ErtsNumber]} = re:run(erlang:system_info(otp_release), "(\\d+)", [{capture, [0], list}]),
-ErtsVsn = erlang:list_to_integer(ErtsNumber),
-AddErlOpts = if
-                 ErtsVsn >= 15 ->
-                     [{d, have_callback_support}];
-                 true ->
-                     []
-             end,
-
-DevOnlyDeps = [{neotoma, "",
-                {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}},
-               {proper, "",
-                {git, "https://github.com/bkearns/proper.git", {branch, master}}}],
-
-Config1 = MergeConfig({erl_opts, AddErlOpts}, CONFIG),
-
-ConfigPath = filename:dirname(SCRIPT),
-DevMarker = filename:join([ConfigPath, ".DEV_MODE"]),
-case filelib:is_file(DevMarker) of
-    true ->
-        lists:foldl(MergeConfig, Config1,
-                    [{deps, DevOnlyDeps},
-                     {erl_opts, [{d, 'DEV_ONLY'}]}]);
-    false ->
-        Config1
-end.
-
diff --git a/rebar.lock b/rebar.lock
new file mode 100644
index 0000000..57afcca
--- /dev/null
+++ b/rebar.lock
@@ -0,0 +1 @@
+[].
diff --git a/rebar3 b/rebar3
new file mode 100755
index 0000000000000000000000000000000000000000..c44f8085b33c2f22acd8df13eccced7e400aeff3
GIT binary patch
literal 352647
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

2fh5Eqi1$XzJWQAh`mhMH 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

_^kcbg#fp`!9AX*OGe)clwVYk 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 literal 0 HcmV?d00001 diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index 042c56a..0ccc457 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,7 +1,13 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "semver"}, + {vsn, "0.13.0"}, {modules, []}, {registered, []}, - {applications, [kernel, stdlib]}]}. + {applications, [kernel, stdlib]}, + + {contributors,["Eric Merritt", "Tristan Sloughter", + "Jordan Wilberding", "Martin Logan"]}, + {licenses, ["Apache"]}, + {links, [{"Github","https://github.com/erlware/erlware_commons"}]} + ]}. From 2d634c5e469abf98e4fab25f8fdca4507c70bce0 Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Fri, 10 Jul 2015 09:12:16 -0700 Subject: [PATCH 117/240] Made version prefix configurable in ec_git_vsn --- README.md | 2 +- src/ec_git_vsn.erl | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3a8ed83..d4e53eb 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ the `lists` module in stdlib. ### [ec_talk](https://github.com/erlware/erlware_commons/blob/master/src/ec_talk.erl) -A set of simple utility functions to falicitate command line +A set of simple utility functions to facilitate command line communication with a user. Signatures diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl index 680b194..cc51a92 100644 --- a/src/ec_git_vsn.erl +++ b/src/ec_git_vsn.erl @@ -24,7 +24,7 @@ %%%=================================================================== %% This should be opaque, but that kills dialyzer so for now we export it %% however you should not rely on the internal representation here --type t() :: {}. +-type t() :: {string()}. %%%=================================================================== %%% API @@ -32,23 +32,23 @@ -spec new() -> t(). new() -> - {}. + {"v"}. -spec vsn(t()) -> {ok, string()} | {error, Reason::any()}. -vsn(_Data) -> - {Vsn, RawRef, RawCount} = collect_default_refcount(), +vsn(Data) -> + {Vsn, RawRef, RawCount} = collect_default_refcount(Data), {ok, build_vsn_string(Vsn, RawRef, RawCount)}. %%%=================================================================== %%% Internal Functions %%%=================================================================== -collect_default_refcount() -> +collect_default_refcount(Data) -> %% Get the tag timestamp and minimal ref from the system. The %% timestamp is really important from an ordering perspective. RawRef = os:cmd("git log -n 1 --pretty=format:'%h\n' "), - {Tag, TagVsn} = parse_tags(), + {Tag, TagVsn} = parse_tags(Data), RawCount = case Tag of undefined -> @@ -84,11 +84,14 @@ get_patch_count(RawRef) -> [Ref]), os:cmd(Cmd). -parse_tags() -> - first_valid_tag(os:cmd("git log --oneline --decorate | fgrep \"tag: \" -1000")). +-spec parse_tags(t()) -> {string()|undefined, ec_semver:version_string()}. +parse_tags({Prefix}) -> + first_valid_tag(os:cmd("git log --oneline --decorate | fgrep \"tag: \" -1000"), Prefix). -first_valid_tag(Line) -> - case re:run(Line, "(\\(|\\s)tag:\\s(v([^,\\)]+))", [{capture, [2, 3], list}]) of +-spec first_valid_tag(string(), string()) -> {string()|undefined, ec_semver:version_string()}. +first_valid_tag(Line, Prefix) -> + RE = lists:flatten(io_lib:format("(\\(|\\s)tag:\\s(~s([^,\\)]+))", [Prefix])), + case re:run(Line, RE, [{capture, [2, 3], list}]) of {match,[Tag, Vsn]} -> {Tag, Vsn}; nomatch -> From 381189c0064e8bb30ed77b3a464e12f147a58667 Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Sun, 12 Jul 2015 07:31:08 -0700 Subject: [PATCH 118/240] Made grep version command's grep POSIX --- src/ec_git_vsn.erl | 5 ++++- test/ec_git_vsn_tests.erl | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/ec_git_vsn_tests.erl diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl index cc51a92..e832e84 100644 --- a/src/ec_git_vsn.erl +++ b/src/ec_git_vsn.erl @@ -86,7 +86,10 @@ get_patch_count(RawRef) -> -spec parse_tags(t()) -> {string()|undefined, ec_semver:version_string()}. parse_tags({Prefix}) -> - first_valid_tag(os:cmd("git log --oneline --decorate | fgrep \"tag: \" -1000"), Prefix). + first_valid_tag(os:cmd("git log --oneline --decorate | grep -F \"tag: \""), Prefix). + %% TODO: The following command sould be able to get the version + %% number directly, without a re:run. Should be checked for POSIX + %% "git log --oneline --decorate | grep -F \"tag: \" --color=never | head -n 1 | sed \"s/.*tag: " ++ Prefix ++ "\([^,)]*\).*/\1/\"". -spec first_valid_tag(string(), string()) -> {string()|undefined, ec_semver:version_string()}. first_valid_tag(Line, Prefix) -> diff --git a/test/ec_git_vsn_tests.erl b/test/ec_git_vsn_tests.erl new file mode 100644 index 0000000..b21abc1 --- /dev/null +++ b/test/ec_git_vsn_tests.erl @@ -0,0 +1,15 @@ +-module(ec_git_vsn_tests). +-include_lib("eunit/include/eunit.hrl"). +-compile([export_all]). + + +%% Hi! This test only works because you've cloned this repo out of git +%% AND we're tagging this repo with a "v" prefix. Hey, it's better +%% than nothing. +vsn_grep_test() -> + {ok, VSN} = ec_git_vsn:vsn({"v"}), + + [$v|OtherVSN] = os:cmd("git tag | xargs -I@ git log --format=format:\"%ai @%n\" -1 @ | sort -r | awk '{print $4}' | head -n 1"), + + ?assertEqual(OtherVSN, VSN ++ "\n"), + ok. From 6813d5184c76c7b35ba5c6c2ff5db00378b23f73 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sun, 12 Jul 2015 11:10:27 -0500 Subject: [PATCH 119/240] version bump --- src/erlware_commons.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index 0ccc457..a5a2d64 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- {application, erlware_commons, [{description, "Additional standard library for Erlang"}, - {vsn, "0.13.0"}, + {vsn, "0.15.0"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib]}, From 885a516f034e9fc9aadfafc1f18058b40f16e5e3 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 4 Sep 2015 10:48:21 -0700 Subject: [PATCH 120/240] remove proper as a testing tool from the package PropEr has a problematic license and that makes it unusable. Historically, there was some ideas that it was going to change but it never did. --- doc/property_based_testing.md | 363 ---------------------------------- rebar.config | 7 +- src/ec_cnv.erl | 62 ------ test/ec_dictionary_proper.erl | 226 --------------------- 4 files changed, 3 insertions(+), 655 deletions(-) delete mode 100644 doc/property_based_testing.md delete mode 100644 test/ec_dictionary_proper.erl diff --git a/doc/property_based_testing.md b/doc/property_based_testing.md deleted file mode 100644 index 414c962..0000000 --- a/doc/property_based_testing.md +++ /dev/null @@ -1,363 +0,0 @@ -Property based testing for unit testers -======================================= - -Main contributors: Torben Hoffmann, Raghav Karol, Eric Merritt - -The purpose of the short document is to help people who are familiar -with unit testing understand how property based testing (PBT) differs, -but also where the thinking is the same. - -This document focusses on the PBT tool -[`PropEr`](https://github.com/manopapad/proper) for Erlang since that is -what I am familiar with, but the general principles applies to all PBT -tools regardless of which language they are written in. - -The approach taken here is that we hear from people who are used to -working with unit testing regarding how they think when designing -their tests and how a concrete test might look. - -These descriptions are then "converted" into the way it works with -PBT, with a clear focus on what stays the same and what is different. - -## Testing philosophies - -### A quote from Martin Logan: - -> For me unit testing is about contracts. I think about the same things -> I think about when I write statements like {ok, Resp} = -> Mod:Func(Args). Unit testing and writing specs are very close for me. -> Hypothetically speaking lets say a function should return return {ok, -> string()} | {error, term()} for all given input parameters then my -> unit tests should be able to show that for a representative set of -> input parameters that those contracts are honored. The art comes in -> thinking about what that set is. - - -The trap in writing all your own tests can often be that we think -about the set in terms of what we coded for and not what may indeed be -asked of our function. As the code is tried in further exploratory -testing and in production new input parameter sets for which the given -function does not meet the stated contract are discovered and added to -the test case once a fix has been put into place. - -This is a very good description of what the ground rules for unit -testing are: - -* Checking that contracts are obeyed. -* Creating a representative set of input parameters. - -The former is very much part of PBT - each property you write will -check a contract, so that thinking is the same. - -## xUnit vs PBT - -Unit testing has become popular for software testing with the advent -of xUnit tools like jUnit for Java. xUnit like tools typically -provide a testing framework with the following functionality - -* test fixture setup -* test case execution -* test fixture teardown -* test suite management -* test status reporting and management - -While xUnit tools provide a lot of functionality to execute and manage -test cases and suites, reporting results there is no focus on test -case execution step, while this is the main focus area of -property-based testing (PBT). - -Consider the following function specification - - :::erlang - sort(list::integer()) ---> list::integer() | error - -A verbal specification of this function is, - -> For all input lists of integers, the sort function returns a sorted -> list of integers. - -For any other kind of argument the function returns the atom error. - -The specification above may be a requirement of how the function -should behave or even how the function does behave. This distinction -is important; the former is the requirement for the function, the -latter is the actual API. Both should be the same and that is what our -testing should confirm. Test cases for this function might look like - - :::erlang - assertEqual(sort([5,4,3,2,1]), [1,2,3,4,5]) - assertEqual(sort([1,2,3,4,5]), [1,2,3,4,5]) - assertEqual(sort([] ), [] ) - assertEqual(sort([-1,0, 1] ), [-1, 0, 1] ) - -How many tests cases should we write to be convinced that the actual -behaviour of the function is the same as its specification? Clearly, -it is impossible to write tests cases for all possible input values, -here all lists of integers, the art of testing is finding individual -input values that are representative of a large part of the input -space. We hope that the test cases are exhaustive to cover the -specification. xUnit tools offer no support for this and this is where -PBT and PBT Tools like `PropEr` and `QuickCheck` come in. - -PBT introduces testing with a large set of random input values and -verifying that the specification holds for each input value -selected. Functions used to generate input values, generators, are -specified using rules and can be simply composed together to construct -complicated values. So, a property based test for the function above -may look like: - - :::erlang - FOREACH({I, J, InputList}, {nat(), nat(), integer_list()}, - SUCHTHAT(I < J andalso J < length(InputList), - SortedList = sort(InputList) - length(SortedList) == length(InputList) - andalso - lists:get(SortedList, I) =< lists:get(SortedList, J)) - - -The property above works as follows - -* Generate a random list of integers `InputList` and two natural numbers - I, J, such that I < J < size of `InputList` -* Check that size of sorted and input lists is the same. -* Check that element with smaller index I is less than or equal to - element with larger index J in `SortedList`. - -Notice in the property above, we *specify* property. Verification of -the property based on random input values will be done by the property -based tool, therefore we can generated a large number of tests cases -with random input values and have a higher level of confidence that -the function when using unit tests alone. - -But it does not stop at generation of input parameters. If you have -more complex tests where you have to generate a series of events and -keep track of some state then your PBT tool will generate random -sequences of events which corresponds to legal sequences of events and -test that your system behaves correctly for all sequences. - -So when you have written a property with associated generators you -have in fact created something that can create numerous test cases - -you just have to tell your PBT tool how many test cases you want to -check the property on. - -## Shrinking the bar - -At this point you might still have the feeling that introducing the -notion of some sort of generators to your unit testing tool of choice -would bring you on par with PBT tools, but wait there is more to -come. - -When a PBT tool creates a test case that fails there is real chance -that it has created a long test case or some big input parameters - -trying to debug that is very much like receiving a humongous log from -a system in the field and try to figure out what cause the system to -fail. - -Enter shrinking... - -When a test case fails the PBT tool will try to shrink the failing -test case down to the essentials by stripping out input elements or -events that does not cause the failure. In most cases this results in -a very short counterexample that clearly states which events and -inputs are required to break a property. - -As we go through some concrete examples later the effects of shrinking -will be shown. - -Shrinking makes it a lot easier to debug problems and is as key to the -strength of PBT as the generators. - -## Converting a unit test - -We will now take a look at one possible way of translating a unit -test into a PBT setting. - -The example comes from Eric Merritt and is about the `add/2` function in -the `ec_dictionary` instance `ec_gb_trees`. - -The add function has the following spec: - - :::erlang - -spec add(ec_dictionary:key(), ec_dictionary:value(), Object::dictionary()) -> - dictionary(). - -and it is supposed to do the obvious: add the key and value pair to -the dictionary and return a new dictionary. - -Eric states his basic expectations as follows: - -1. I can put arbitrary terms into the dictionary as keys -2. I can put arbitrary terms into the dictionary as values -3. When I put a value in the dictionary by a key, I can retrieve that same value -4. When I put a different value in the dictionary by key it does not change other key value pairs. -5. When I update a value the new value in available by the new key -6. When a value does not exist a not found exception is created - -The first two expectations regarding being able to use arbritrary -terms as keys and values is a job for generators. - -The latter four are prime candidates for properties and we will create -one for each of them. - -### Generators - - :::erlang - key() -> any(). - - value() -> any(). - - -For `PropEr` this approach has the drawback that creation and shrinking -becomes rather time consuming, so it might be better to narrow to -something like this: - - :::erlang - key() -> union([integer(),atom()]). - - value() -> union([integer(),atom(),binary(),boolean(),string()]). - -What is best depends on the situation and intended usage. - -Now, being able to generate keys and values is not enough. You also -have to tell `PropEr` how to create a dictionary and in this case we -will use a symbolic generator (detail to be explained later). - - :::erlang - sym_dict() -> - ?SIZED(N,sym_dict(N)). - - sym_dict(0) -> - {'$call',ec_dictionary,new,[ec_gb_trees]}; - sym_dict(N) -> - ?LAZY( - frequency([ - {1, {'$call',ec_dictionary,remove,[key(),sym_dict(N-1)]}}, - {2, {'$call',ec_dictionary,add,[value(),value(),sym_dict(N-1)]}} - ])). - - -`sym_dict/0` uses the `?SIZED` macro to control the size of the -generated dictionary. `PropEr` will start out with small numbers and -gradually raise it. - -`sym_dict/1` is building a dictionary by randomly adding key/value -pairs and removing keys. Eventually the base case is reached which -will create an empty dictionary. - -The `?LAZY` macro is used to defer the calculation of the -`sym_dict(N-1)` until they are needed and `frequency/1` is used -to ensure that twice as many adds compared to removes are done. This -should give rather more interesting dictionaries in the long run, if -not one can alter the frequencies accondingly. - -But does it really work? - -That is a good question and one that should always be asked when -looking at genetors. Fortunately there is a way to see what a -generator produces provided that the generator functions are exported. - -Hint: in most cases it will not hurt to throw in a -`-compile(export_all).` in the module used to specify the -properties. And here we actually have a sub-hint: specify the -properties in a separate file to avoid peeking inside the -implementation! Base the test on the published API as this is what the -users of the code will be restricted to. - -When the test module has been loaded you can test the generators by -starting up an Erlang shell (this example uses the erlware_commons -code so get yourself a clone to play with): - - :::sh - $ erl -pz ebin -pz test - 1> proper_gen:pick(ec_dictionary_proper:key()). - {ok,4} - 2> proper_gen:pick(ec_dictionary_proper:key()). - {ok,35} - 3> proper_gen:pick(ec_dictionary_proper:key()). - {ok,-5} - 4> proper_gen:pick(ec_dictionary_proper:key()). - {ok,48} - 5> proper_gen:pick(ec_dictionary_proper:key()). - {ok,'\036\207_là´?\nc'} - 6> proper_gen:pick(ec_dictionary_proper:value()). - {ok,2} - 7> proper_gen:pick(ec_dictionary_proper:value()). - {ok,-14} - 8> proper_gen:pick(ec_dictionary_proper:value()). - {ok,-3} - 9> proper_gen:pick(ec_dictionary_proper:value()). - {ok,27} - 10> proper_gen:pick(ec_dictionary_proper:value()). - {ok,-8} - 11> proper_gen:pick(ec_dictionary_proper:value()). - {ok,[472765,17121]} - 12> proper_gen:pick(ec_dictionary_proper:value()). - {ok,true} - 13> proper_gen:pick(ec_dictionary_proper:value()). - {ok,<<>>} - 14> proper_gen:pick(ec_dictionary_proper:value()). - {ok,<<89,69,18,148,32,42,238,101>>} - 15> proper_gen:pick(ec_dictionary_proper:sym_dict()). - {ok,{'$call',ec_dictionary,add, - [[114776,1053475], - 'fª\020\227\215', - {'$call',ec_dictionary,add, - ['',true, - {'$call',ec_dictionary,add, - ['2^Ø¡', - [900408,886056], - {'$call',ec_dictionary,add,[[48618|...],<<...>>|...]}]}]}]}} - 16> proper_gen:pick(ec_dictionary_proper:sym_dict()). - {ok,{'$call',ec_dictionary,add, - [10,'a¯\214\031fõC', - {'$call',ec_dictionary,add, - [false,-1, - {'$call',ec_dictionary,remove, - ['d·ÉV÷[', - {'$call',ec_dictionary,remove,[12,{'$call',...}]}]}]}]}} - -That does not look too bad, so we will continue with that for now. - - -### Properties of `add/2` - -The first expectation Eric had about how the dictionary works was that -if a key had been stored it could be retrieved. - -One way of expressing this could be with this property: - - :::erlang - prop_get_after_add_returns_correct_value() -> - ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, - begin - try ec_dictionary:get(K,ec_dictionary:add(K,V,Dict)) of - V -> - true; - _ -> - false - catch - _:_ -> - false - end - end). - -This property reads that for all dictionaries `get/2` using a key -from a key/value pair just inserted using the `add/3` function -will return that value. If that is not the case the property will -evaluate to false. - -Running the property is done using `proper:quickcheck/1`: - - :::sh - proper:quickcheck(ec_dictionary_proper:prop_get_after_add_returns_correct_value()). - .................................................................................................... - OK: Passed 100 test(s). - true - - -This was as expected, but at this point we will take a little detour -and introduce a mistake in the `ec_gb_trees` implementation and see -how that works. - - - diff --git a/rebar.config b/rebar.config index 48d5b07..7f67a43 100644 --- a/rebar.config +++ b/rebar.config @@ -21,8 +21,7 @@ {cover_print_enabled, true}. %% Profiles ==================================================================== -{profiles, [{dev, [{deps, [{neotoma, "", - {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}, - {proper, "", - {git, "https://github.com/bkearns/proper.git", {branch, master}}}]}]} +{profiles, [{dev, [{deps, + [{neotoma, "", + {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}]}]} ]}. diff --git a/src/ec_cnv.erl b/src/ec_cnv.erl index 80b05e7..8976549 100644 --- a/src/ec_cnv.erl +++ b/src/ec_cnv.erl @@ -33,10 +33,6 @@ is_true/1, is_false/1]). --ifdef(DEV_ONLY). --include_lib("proper/include/proper.hrl"). --endif. - %%%=================================================================== %%% API %%%=================================================================== @@ -224,10 +220,6 @@ to_atom(X) -> -ifdef(DEV_ONLY). -include_lib("eunit/include/eunit.hrl"). -force_proper_test_() -> - {"Runs PropEr test during EUnit phase", - {timeout, 15000, [?_assertEqual([], proper:module(?MODULE))]}}. - to_integer_test() -> ?assertError(badarg, to_integer(1.5, strict)). @@ -252,58 +244,4 @@ to_boolean_test()-> ?assertMatch(false, to_boolean("false")), ?assertMatch(false, to_boolean(false)). -%%% PropEr testing - -prop_to_integer() -> - ?FORALL({F, I}, {float(), integer()}, - begin - Is = [[Fun(N), N] || - Fun <- [fun to_list/1, - fun to_binary/1], - N <- [F, I]], - lists:all(fun([FN, N]) -> - erlang:is_integer(to_integer(N)) andalso - erlang:is_integer(to_integer(FN)) - end, Is) - end). - -prop_to_list() -> - ?FORALL({A, L, B, I, F}, {atom(), list(), binary(), integer(), float()}, - lists:all(fun(X) -> - erlang:is_list(to_list(X)) - end, [A, L, B, I, F])). - -prop_to_binary() -> - ?FORALL({A, L, B, I, F, IO}, {atom(), list(range(0,255)), binary(), - integer(), float(), iolist()}, - lists:all(fun(X) -> - erlang:is_binary(to_binary(X)) - end, [A, L, B, I, F, IO])). - -prop_iolist_t() -> - ?FORALL(IO, iolist(), erlang:is_binary(to_binary(IO))). - -prop_to_float() -> - ?FORALL({F, I}, {float(), integer()}, - begin - Fs = [[Fun(N), N] || - Fun <- [fun to_list/1, fun to_binary/1], - N <- [F, I]], - lists:all(fun([FN, N]) -> - erlang:is_float(to_float(N)) andalso - erlang:is_float(to_float(FN)) - end, Fs) - end). - -prop_to_number() -> - ?FORALL({F, I}, {float(), integer()}, - begin - Is = [[Fun(N), N] || - Fun <- [fun to_list/1, fun to_binary/1], - N <- [F, I] ], - lists:all(fun([FN, N]) -> - erlang:is_number(to_number(N)) andalso - erlang:is_number(to_number(FN)) - end, Is) - end). -endif. diff --git a/test/ec_dictionary_proper.erl b/test/ec_dictionary_proper.erl deleted file mode 100644 index a455e90..0000000 --- a/test/ec_dictionary_proper.erl +++ /dev/null @@ -1,226 +0,0 @@ -%% compile with -%% erl -pz ebin --make -%% start test with -%% erl -pz ebin -pz test -%% proper:module(ec_dictionary_proper). --module(ec_dictionary_proper). - --ifdef(DEV_ONLY). - --export([my_dict/0, dict/1, sym_dict/0, sym_dict/1, gb_tree/0, gb_tree/1, sym_dict2/0]). - --include_lib("proper/include/proper.hrl"). - - -%%------------------------------------------------------------------------------ -%% Properties -%%------------------------------------------------------------------------------ - -prop_size_increases_with_new_key() -> - ?FORALL({Dict,K}, {sym_dict(),integer()}, - begin - Size = ec_dictionary:size(Dict), - case ec_dictionary:has_key(K,Dict) of - true -> - Size == ec_dictionary:size(ec_dictionary:add(K,0,Dict)); - false -> - (Size + 1) == ec_dictionary:size(ec_dictionary:add(K,0,Dict)) - end - end). - -prop_size_decrease_when_removing() -> - ?FORALL({Dict,K}, {sym_dict(),integer()}, - begin - Size = ec_dictionary:size(Dict), - case ec_dictionary:has_key(K,Dict) of - false -> - Size == ec_dictionary:size(ec_dictionary:remove(K,Dict)); - true -> - (Size - 1) == ec_dictionary:size(ec_dictionary:remove(K,Dict)) - end - end). - -prop_get_after_add_returns_correct_value() -> - ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, - begin - try ec_dictionary:get(K,ec_dictionary:add(K,V,Dict)) of - V -> - true; - _ -> - false - catch - _:_ -> - false - end - end). - -prop_get_default_returns_correct_value() -> - ?FORALL({Dict,K1,K2,V,Default}, - {sym_dict(),key(),key(),value(),value()}, - begin - NewDict = ec_dictionary:add(K1,V, Dict), - %% In the unlikely event that keys that are the same - %% are generated - case ec_dictionary:has_key(K2, NewDict) of - true -> - true; - false -> - ec_dictionary:get(K2, Default, NewDict) == Default - end - end). - - -prop_add_does_not_change_values_for_other_keys() -> - ?FORALL({Dict,K,V}, {sym_dict(),key(),value()}, - begin - Keys = ec_dictionary:keys(Dict), - ?IMPLIES(not lists:member(K,Keys), - begin - Dict2 = ec_dictionary:add(K,V,Dict), - try lists:all(fun(B) -> B end, - [ ec_dictionary:get(Ka,Dict) == - ec_dictionary:get(Ka,Dict2) || - Ka <- Keys ]) of - Bool -> Bool - catch - throw:not_found -> true - end - end) - end). - - - -prop_key_is_present_after_add() -> - ?FORALL({Dict,K,V}, {sym_dict(),integer(),integer()}, - begin - ec_dictionary:has_key(K,ec_dictionary:add(K,V,Dict)) end). - -prop_value_is_present_after_add() -> - ?FORALL({Dict,K,V}, {sym_dict(),integer(),integer()}, - begin - ec_dictionary:has_value(V,ec_dictionary:add(K,V,Dict)) - end). - -prop_to_list_matches_get() -> - ?FORALL(Dict,sym_dict(), - begin - %% Dict = eval(SymDict), - %% io:format("SymDict: ~p~n",[proper_symb:symbolic_seq(SymDict)]), - ToList = ec_dictionary:to_list(Dict), - %% io:format("ToList:~p~n",[ToList]), - GetList = - try [ {K,ec_dictionary:get(K,Dict)} || {K,_V} <- ToList ] of - List -> List - catch - throw:not_found -> key_not_found - end, - %% io:format("~p == ~p~n",[ToList,GetList]), - lists:sort(ToList) == lists:sort(GetList) - end). - -prop_value_changes_after_update() -> - ?FORALL({Dict, K1, V1, V2}, - {sym_dict(), - key(), value(), value()}, - begin - Dict1 = ec_dictionary:add(K1, V1, Dict), - Dict2 = ec_dictionary:add(K1, V2, Dict1), - V1 == ec_dictionary:get(K1, Dict1) andalso - V2 == ec_dictionary:get(K1, Dict2) - end). - -prop_remove_removes_only_one_key() -> - ?FORALL({Dict,K}, - {sym_dict(),key()}, - begin - {KeyGone,Dict2} = case ec_dictionary:has_key(K,Dict) of - true -> - D2 = ec_dictionary:remove(K,Dict), - {ec_dictionary:has_key(K,D2) == false, - D2}; - false -> - {true,ec_dictionary:remove(K,Dict)} - end, - OtherEntries = [ KV || {K1,_} = KV <- ec_dictionary:to_list(Dict), - K1 /= K ], - KeyGone andalso - lists:sort(OtherEntries) == lists:sort(ec_dictionary:to_list(Dict2)) - end). - -prop_from_list() -> - ?FORALL({Dict,DictType}, - {sym_dict(),dictionary()}, - begin - List = ec_dictionary:to_list(Dict), - D2 = ec_dictionary:from_list(DictType,List), - List2 = ec_dictionary:to_list(D2), - lists:sort(List) == lists:sort(List2) - end). - - -%%----------------------------------------------------------------------------- -%% Generators -%%----------------------------------------------------------------------------- - -key() -> union([integer(),atom()]). - -value() -> union([integer(),atom(),binary(),boolean(),string()]). - - -my_dict() -> - ?SIZED(N,dict(N)). - - -dict(0) -> - ec_dictionary:new(ec_gb_trees); -dict(N) -> - ?LET(D,dict(N-1), - frequency([ - {1, dict(0)}, - {3, ec_dictionary:remove(integer(),D)}, - {6, ec_dictionary:add(integer(),integer(),D)} - ])). - -sym_dict() -> - ?SIZED(N,sym_dict(N)). - -%% This symbolic generator will create a random instance of a ec_dictionary -%% that will be used in the properties. -sym_dict(0) -> - ?LET(Dict,dictionary(), - {'$call',ec_dictionary,new,[Dict]}); -sym_dict(N) -> - ?LAZY( - frequency([ - {1, sym_dict(0)}, - {3, {'$call',ec_dictionary,remove,[key(),sym_dict(N-1)]}}, - {6, {'$call',ec_dictionary,add,[value(),value(),sym_dict(N-1)]}} - ]) - ). - -dictionary() -> - union([ec_gb_trees,ec_assoc_list,ec_dict,ec_orddict]). - -sym_dict2() -> - ?SIZED(N,sym_dict2(N)). - -sym_dict2(0) -> - {call,ec_dictionary,new,[ec_gb_trees]}; -sym_dict2(N) -> - D = dict(N-1), - frequency([ - {1, {call,ec_dictionary,remove,[integer(),D]}}, - {2, {call,ec_dictionary,add,[integer(),integer(),D]}} - ]). - - -%% For the tutorial. -gb_tree() -> - ?SIZED(N,gb_tree(N)). - -gb_tree(0) -> - gb_trees:empty(); -gb_tree(N) -> - gb_trees:enter(key(),value(),gb_tree(N-1)). - --endif. From fbf7f7951cc3ec87dd57aef5c51e10e687c4dfd5 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 4 Sep 2015 10:52:58 -0700 Subject: [PATCH 121/240] Add R18 (18.0) to the list of travis builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fcb6c23..7d9265c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: erlang otp_release: + - 18.0 - 17.0 - R16B03-1 - R16B03 From 739a9bcf243d94c3f2602f6d82b3a92793b9fa88 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 7 Sep 2015 10:45:58 -0700 Subject: [PATCH 122/240] Swap DEV_ONLY for TEST in the test exclusion macros --- src/ec_cmd_log.erl | 2 +- src/ec_cnv.erl | 2 +- src/ec_date.erl | 2 +- src/ec_file.erl | 2 +- src/ec_gb_trees.erl | 2 +- src/ec_lists.erl | 2 +- src/ec_semver.erl | 2 +- src/ec_talk.erl | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 4c54086..66ee40c 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -243,7 +243,7 @@ term_capabilities(_) -> full. %% Default to the backwards compatible version. %%% Test Functions %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). should_test() -> diff --git a/src/ec_cnv.erl b/src/ec_cnv.erl index 8976549..72700fb 100644 --- a/src/ec_cnv.erl +++ b/src/ec_cnv.erl @@ -217,7 +217,7 @@ to_atom(X) -> %%% Tests %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). to_integer_test() -> diff --git a/src/ec_date.erl b/src/ec_date.erl index f04e399..c21c2a8 100644 --- a/src/ec_date.erl +++ b/src/ec_date.erl @@ -694,7 +694,7 @@ ltoi(X) -> %%% Tests %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/src/ec_file.erl b/src/ec_file.erl index e283c64..46ed814 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -325,7 +325,7 @@ sub_files(From) -> %%% Test Functions %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). setup_test() -> diff --git a/src/ec_gb_trees.erl b/src/ec_gb_trees.erl index a87ab86..7985fab 100644 --- a/src/ec_gb_trees.erl +++ b/src/ec_gb_trees.erl @@ -141,7 +141,7 @@ keys(Data) -> %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). %% For me unit testing initially is about covering the obvious case. A diff --git a/src/ec_lists.erl b/src/ec_lists.erl index fd8fa5f..c95078b 100644 --- a/src/ec_lists.erl +++ b/src/ec_lists.erl @@ -68,7 +68,7 @@ fetch(Fun, List) when is_list(List), is_function(Fun) -> %%% Test Functions %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). find1_test() -> diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 23ba311..0298872 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -314,7 +314,7 @@ internal_pes(Vsn, LVsn) -> %%% Test Functions %%%=================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). eql_test() -> diff --git a/src/ec_talk.erl b/src/ec_talk.erl index 5e24f2c..5d79b64 100644 --- a/src/ec_talk.erl +++ b/src/ec_talk.erl @@ -200,7 +200,7 @@ get_string(String) -> %%%==================================================================== %%% tests %%%==================================================================== --ifdef(DEV_ONLY). +-ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). general_test_() -> From 29c711bc398f360bc5522e3925885a93f8911afc Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Mon, 7 Sep 2015 10:53:36 -0700 Subject: [PATCH 123/240] remove ec_git_vsn_test This test only had one test that dependended entirely on the state of *this* git repository. Tests shouldn't depend on external unmanaged state not changing. --- test/ec_git_vsn_tests.erl | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 test/ec_git_vsn_tests.erl diff --git a/test/ec_git_vsn_tests.erl b/test/ec_git_vsn_tests.erl deleted file mode 100644 index b21abc1..0000000 --- a/test/ec_git_vsn_tests.erl +++ /dev/null @@ -1,15 +0,0 @@ --module(ec_git_vsn_tests). --include_lib("eunit/include/eunit.hrl"). --compile([export_all]). - - -%% Hi! This test only works because you've cloned this repo out of git -%% AND we're tagging this repo with a "v" prefix. Hey, it's better -%% than nothing. -vsn_grep_test() -> - {ok, VSN} = ec_git_vsn:vsn({"v"}), - - [$v|OtherVSN] = os:cmd("git tag | xargs -I@ git log --format=format:\"%ai @%n\" -1 @ | sort -r | awk '{print $4}' | head -n 1"), - - ?assertEqual(OtherVSN, VSN ++ "\n"), - ok. From 7c37ecf949fae309f742f7b0ba9cd7c9730a6ff6 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sat, 19 Sep 2015 13:05:52 -0500 Subject: [PATCH 124/240] make v optional as prefix to version in git_vsn --- src/ec_git_vsn.erl | 16 ++++++++-------- test/ec_plists_tests.erl | 3 --- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/ec_git_vsn.erl b/src/ec_git_vsn.erl index e832e84..9c0a1db 100644 --- a/src/ec_git_vsn.erl +++ b/src/ec_git_vsn.erl @@ -24,7 +24,7 @@ %%%=================================================================== %% This should be opaque, but that kills dialyzer so for now we export it %% however you should not rely on the internal representation here --type t() :: {string()}. +-type t() :: {}. %%%=================================================================== %%% API @@ -32,7 +32,7 @@ -spec new() -> t(). new() -> - {"v"}. + {}. -spec vsn(t()) -> {ok, string()} | {error, Reason::any()}. vsn(Data) -> @@ -85,15 +85,15 @@ get_patch_count(RawRef) -> os:cmd(Cmd). -spec parse_tags(t()) -> {string()|undefined, ec_semver:version_string()}. -parse_tags({Prefix}) -> - first_valid_tag(os:cmd("git log --oneline --decorate | grep -F \"tag: \""), Prefix). +parse_tags(_) -> + first_valid_tag(os:cmd("git log --oneline --decorate | grep -F \"tag: \"")). %% TODO: The following command sould be able to get the version %% number directly, without a re:run. Should be checked for POSIX - %% "git log --oneline --decorate | grep -F \"tag: \" --color=never | head -n 1 | sed \"s/.*tag: " ++ Prefix ++ "\([^,)]*\).*/\1/\"". + %% "git log --oneline --decorate | grep -F \"tag: \" --color=never | head -n 1 | sed \"s/.*tag: v?\([^,)]*\).*/\1/\"". --spec first_valid_tag(string(), string()) -> {string()|undefined, ec_semver:version_string()}. -first_valid_tag(Line, Prefix) -> - RE = lists:flatten(io_lib:format("(\\(|\\s)tag:\\s(~s([^,\\)]+))", [Prefix])), +-spec first_valid_tag(string()) -> {string()|undefined, ec_semver:version_string()}. +first_valid_tag(Line) -> + RE = "(\\(|\\s)tag:\\s(v?([^,\\)]+))", case re:run(Line, RE, [{capture, [2, 3], list}]) of {match,[Tag, Vsn]} -> {Tag, Vsn}; diff --git a/test/ec_plists_tests.erl b/test/ec_plists_tests.erl index ff5d2e9..3f050ac 100644 --- a/test/ec_plists_tests.erl +++ b/test/ec_plists_tests.erl @@ -1,8 +1,6 @@ %%% @copyright Erlware, LLC. -module(ec_plists_tests). --ifdef(DEV_ONLY). - -include_lib("eunit/include/eunit.hrl"). %%%=================================================================== @@ -76,4 +74,3 @@ ftmap_bad_test() -> ?assertMatch([{value, 1}, {error,{throw,test_exception}}, {value, 3}, {value, 4}, {value, 5}] , Results). --endif. From 3608a576fb7b6cee17c623aee40f04db2a8b98b0 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 21 Jul 2015 10:19:10 -0500 Subject: [PATCH 125/240] version bump to 0.16.0 --- src/erlware_commons.app.src | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index a5a2d64..c4ad6a7 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,13 +1,11 @@ -%% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*- -{application, erlware_commons, - [{description, "Additional standard library for Erlang"}, - {vsn, "0.15.0"}, - {modules, []}, - {registered, []}, - {applications, [kernel, stdlib]}, - - {contributors,["Eric Merritt", "Tristan Sloughter", - "Jordan Wilberding", "Martin Logan"]}, - {licenses, ["Apache"]}, - {links, [{"Github","https://github.com/erlware/erlware_commons"}]} - ]}. +{application,erlware_commons, + [{description,"Additional standard library for Erlang"}, + {vsn,"0.16.0"}, + {modules,[]}, + {registered,[]}, + {applications,[kernel,stdlib]}, + {contributors,["Eric Merritt","Tristan Sloughter", + "Jordan Wilberding","Martin Logan"]}, + {licenses,["Apache"]}, + {links,[{"Github", + "https://github.com/erlware/erlware_commons"}]}]}. From 87c76aeb2a9476f4341b715336046e57b03a3ffb Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Wed, 23 Sep 2015 20:41:15 +0200 Subject: [PATCH 126/240] Alow less colourful output Basically this adds a new/3 with a third argument of intensity. The default (and by that the behaviour of new/1 and /2) remain unchanged so existing code isn't affected. If intenisty is set to `low` (instead of `high`) then only the prefix is coloured making the whole output less colourful and for some cases easyer to read. --- rebar.config | 2 +- rebar.lock | 2 +- src/ec_cmd_log.erl | 58 +++++++++++++++++++++++++++---------- src/erlware_commons.app.src | 2 +- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/rebar.config b/rebar.config index 7f67a43..c20e0f2 100644 --- a/rebar.config +++ b/rebar.config @@ -1,7 +1,7 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- %% Dependencies ================================================================ -{deps, []}. +{deps, [cf]}. {erl_first_files, ["ec_dictionary", "ec_vsn"]}. diff --git a/rebar.lock b/rebar.lock index 57afcca..477758c 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1 +1 @@ -[]. +[{<<"cf">>,{pkg,<<"cf">>,<<"0.1.2">>},0}]. diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 66ee40c..3cd75ae 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -24,6 +24,7 @@ -export([new/1, new/2, + new/3, log/4, should/2, debug/2, @@ -40,17 +41,18 @@ -include("ec_cmd_log.hrl"). --define(RED, 31). --define(GREEN, 32). --define(YELLOW, 33). --define(BLUE, 34). --define(MAGENTA, 35). --define(CYAN, 36). +-define(RED, $r). +-define(GREEN, $g). +-define(YELLOW, $y). +-define(BLUE, $b). +-define(MAGENTA, $m). +-define(CYAN, $c). -define(PREFIX, "===> "). -record(state_t, {log_level=0 :: int_log_level(), caller=api :: caller(), + intensity=low :: low | high, term_cap=full :: full | dumb }). %%============================================================================ @@ -71,9 +73,11 @@ -type atom_log_level() :: error | warn | info | debug. +-type intensity() :: low | high. + -type log_fun() :: fun(() -> iolist()). --type color() :: 31..36. +-type color() :: char(). -opaque t() :: #state_t{}. @@ -86,9 +90,17 @@ new(LogLevel) -> new(LogLevel, api). -spec new(log_level(), caller()) -> t(). -new(LogLevel, Caller) when LogLevel >= 0, LogLevel =< 3 -> - #state_t{log_level=LogLevel, caller=Caller, term_cap=query_term_env()}; -new(AtomLogLevel, Caller) +new(LogLevel, Caller) -> + new(LogLevel, Caller, high). + + +-spec new(log_level(), caller(), intensity()) -> t(). +new(LogLevel, Caller, Intensity) when (Intensity =:= low orelse + Intensity =:= high), + LogLevel >= 0, LogLevel =< 3 -> + #state_t{log_level=LogLevel, caller=Caller, term_cap=query_term_env(), + intensity=Intensity}; +new(AtomLogLevel, Caller, Intensity) when AtomLogLevel =:= error; AtomLogLevel =:= warn; AtomLogLevel =:= info; @@ -99,7 +111,8 @@ new(AtomLogLevel, Caller) info -> 2; debug -> 3 end, - new(LogLevel, Caller). + new(LogLevel, Caller, Intensity). + %% @doc log at the debug level given the current log state with a string or %% function that returns a string @@ -218,10 +231,25 @@ format(Log) -> <<")">>]. -spec colorize(t(), color(), boolean(), string()) -> string(). -colorize(#state_t{caller=command_line, term_cap=full}, Color, false, Msg) when is_integer(Color) -> - lists:flatten(io_lib:format("\033[~B;~Bm~s~s\033[0m", [0, Color, ?PREFIX, Msg])); -colorize(#state_t{caller=command_line, term_cap=dumb}, Color, _Bold, Msg) when is_integer(Color) -> - lists:flatten(io_lib:format("~s~s", [?PREFIX, Msg])); + +-define(VALID_COLOR(C), + C =:= $r orelse C =:= $g orelse C =:= $y orelse + C =:= $b orelse C =:= $m orelse C =:= $c orelse + C =:= $R orelse C =:= $G orelse C =:= $Y orelse + C =:= $B orelse C =:= $M orelse C =:= $C). + +%% We're sneaky we can substract 32 to get the uppercase character +colorize(State, Color, true, Msg) when ?VALID_COLOR(Color) -> + colorize(State, Color - 32, fase, Msg); +colorize(#state_t{caller=command_line, term_cap=full, intensity = high}, + Color, false, Msg) when ?VALID_COLOR(Color) -> + lists:flatten(cf:format("~!" ++ [Color] ++"~s~s", [?PREFIX, Msg])); +colorize(#state_t{caller=command_line, term_cap=full, intensity = low}, + Color, false, Msg) when ?VALID_COLOR(Color) -> + lists:flatten(cf:format("~!" ++ [Color] ++"~s~!!~s", [?PREFIX, Msg])); +colorize(#state_t{caller=command_line, term_cap=dumb}, Color, _Bold, Msg) + when ?VALID_COLOR(Color) -> + lists:flatten(cf:format("~s~s", [?PREFIX, Msg])); colorize(_LogState, _Color, _Bold, Msg) -> Msg. diff --git a/src/erlware_commons.app.src b/src/erlware_commons.app.src index c4ad6a7..899d930 100644 --- a/src/erlware_commons.app.src +++ b/src/erlware_commons.app.src @@ -1,6 +1,6 @@ {application,erlware_commons, [{description,"Additional standard library for Erlang"}, - {vsn,"0.16.0"}, + {vsn,"0.16.1"}, {modules,[]}, {registered,[]}, {applications,[kernel,stdlib]}, From 4aedc36937627557abd0f9deff88d38d74319ff5 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Thu, 24 Sep 2015 19:58:24 +0200 Subject: [PATCH 127/240] Add rebar3 update to test run --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d9265c..b06e34b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ otp_release: - R16B01 - R16B - R15B02 -script: "./rebar3 compile && ./rebar3 ct" +script: "./rebar3 update && ./rebar3 compile && ./rebar3 ct" branches: only: - master From f983b1ac85ebcc1b23654d0b01deeef8a6bb5b9b Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Sat, 31 Oct 2015 18:03:30 +0100 Subject: [PATCH 128/240] Update cmd_log to use cf for color encoding, including term detection --- rebar.lock | 2 +- src/ec_cmd_log.erl | 35 ++++++++++++----------------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/rebar.lock b/rebar.lock index 477758c..cee52da 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1 +1 @@ -[{<<"cf">>,{pkg,<<"cf">>,<<"0.1.2">>},0}]. +[{<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0}]. diff --git a/src/ec_cmd_log.erl b/src/ec_cmd_log.erl index 3cd75ae..1917471 100644 --- a/src/ec_cmd_log.erl +++ b/src/ec_cmd_log.erl @@ -52,8 +52,7 @@ -record(state_t, {log_level=0 :: int_log_level(), caller=api :: caller(), - intensity=low :: low | high, - term_cap=full :: full | dumb }). + intensity=low :: low | high}). %%============================================================================ %% types @@ -98,7 +97,7 @@ new(LogLevel, Caller) -> new(LogLevel, Caller, Intensity) when (Intensity =:= low orelse Intensity =:= high), LogLevel >= 0, LogLevel =< 3 -> - #state_t{log_level=LogLevel, caller=Caller, term_cap=query_term_env(), + #state_t{log_level=LogLevel, caller=Caller, intensity=Intensity}; new(AtomLogLevel, Caller, Intensity) when AtomLogLevel =:= error; @@ -238,35 +237,25 @@ format(Log) -> C =:= $R orelse C =:= $G orelse C =:= $Y orelse C =:= $B orelse C =:= $M orelse C =:= $C). -%% We're sneaky we can substract 32 to get the uppercase character + +%% When it is suposed to be bold and we already have a uppercase +%% (bold color) we don't need to modify the color +colorize(State, Color, true, Msg) when ?VALID_COLOR(Color), + Color >= $A, Color =< $Z -> + colorize(State, Color, fase, Msg); +%% We're sneaky we can substract 32 to get the uppercase character if we want +%% bold but have a non bold color. colorize(State, Color, true, Msg) when ?VALID_COLOR(Color) -> colorize(State, Color - 32, fase, Msg); -colorize(#state_t{caller=command_line, term_cap=full, intensity = high}, +colorize(#state_t{caller=command_line, intensity = high}, Color, false, Msg) when ?VALID_COLOR(Color) -> lists:flatten(cf:format("~!" ++ [Color] ++"~s~s", [?PREFIX, Msg])); -colorize(#state_t{caller=command_line, term_cap=full, intensity = low}, +colorize(#state_t{caller=command_line, intensity = low}, Color, false, Msg) when ?VALID_COLOR(Color) -> lists:flatten(cf:format("~!" ++ [Color] ++"~s~!!~s", [?PREFIX, Msg])); -colorize(#state_t{caller=command_line, term_cap=dumb}, Color, _Bold, Msg) - when ?VALID_COLOR(Color) -> - lists:flatten(cf:format("~s~s", [?PREFIX, Msg])); colorize(_LogState, _Color, _Bold, Msg) -> Msg. -%% @doc Query the term enviroment -%% For reasons of simplicity, we don't parse terminal capabilities yet, although -%% a later version could do so. Rather, we provide a simple match-list of terminal -%% capabilities. -%% @end --spec query_term_env() -> full | dumb. -query_term_env() -> - term_capabilities(os:getenv("TERM")). - --spec term_capabilities(string()) -> full | dumb. -term_capabilities("xterm") -> full; -term_capabilities("dumb") -> dumb; -term_capabilities(_) -> full. %% Default to the backwards compatible version. - %%%=================================================================== %%% Test Functions %%%=================================================================== From 0583ffa67200131b85ea4078698ee2ceb0fcbda9 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Sat, 31 Oct 2015 21:09:26 +0100 Subject: [PATCH 129/240] Update rebar3 --- rebar3 | Bin 352647 -> 733644 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/rebar3 b/rebar3 index c44f8085b33c2f22acd8df13eccced7e400aeff3..84d44f576de0d559dbef0c7ecf59870e8651cc29 100755 GIT binary patch literal 733644 zcmaI7Q;aT5*tPkzciXmY+qP}n=5D)tw{6?DZQHip^L{gvOumDE4k~xnNgb?YRZ`cg zA||AFb#|gRvb3W&wR0mdbvAagbZ~(pB_;T85fV^48@ad=Pzy3ZDM*8Wq5uGZKLF@* zeeu6^Ltbb9sWBh`0PnwPWMu2=>|$taVM=fMKYRUun$FO{!8Tsd8iWub57oYFwT|P)d zzMYKU4Sri$ScaoRXL7D$|4qLK``n|6Gf7^a zAR7-W9_3-kZZGZz=(MWdapj@zywZ3C=gDagKCZl|I~k2{kJ?jfZOW+_#zHx#3uMdN zBr5xF{YU3C{QvgIz25m)3jqMg!vX;C|NlKQGBvbq*7S}?8THI<&*{F_)E&H<9sq(^ z=);NI$KxKQbAX5Yu)DR}<1jD;`rCJPb3LhK5jOlwyw<-m!79OfwIP7hpJDnc?ARb$OY@S9qXuOF#?4N6o)v?WW*7ydM4^79Gh=HFq{kCD*uXSPcBXUC+?tV@ z8}2ehr$Iw(E**YT7B`05rvyC9%W0}AOa>?d!YRZhq*&Lliy_yt8k63l77PE%W;V81 zEB374_1cRYZ&E|9hQ_*=T&v%~dj;_lv_9mz8534n0X}#5#^#hLq-oso@fYnv?V!S+ z9_Sk_en7fKWwlLcA62V#W^ zaryOpQ(1OeQAiBRMO3XW90SWDr3jszP8JEwg499}jl{Y0!Ph~mXh)$C7OK_fk{f(Q z4f6#aFz{1`P+;it*XhOeFVc9=O|r`;S19S1?5CJ+A-#YnjqAVSGJH{^?IO+wN}-HQ zB&hpK5`l3cyiW)s9V-H&WY>kP3)y~}XIg@oo)D1}MhrILV>GM;OH9>nX=B6BlDv2v zR+r?KF^0Jauv{cgBFY5>B#cz>G()^PNSOHBxWHm93=Bpb3qaXM5g!OWgZYDi24Bh@bd)bp;&%;=CAI9@mRw6gZBJAsqL_A(*>I&=~$5h!C+e zt!OTiu7>r9fXHv4@kBxBfhfNXBagXEKm{!en?!G2YL4`#MouF+O(W3Spc6bqmO~=h zk+zJsN{Ytccz=3XVk`;$x$+qFDNP{deFWGk&O%FKO_Dj5u|mjLu9-mBn}QHMUawr% zD6Mg$eY8bnHy-XY85Ga1Hkp(^lelyl@f!7jJ-wsdOL_fxBsRN^8V<(xQF}-{`ghQ4 zx=M84(B`e4dZ0MU1UgvihIxws zaYbSXC;0U?%%haREMO-E1U5aWADeSBY6bYYY$~!z)7=KU2Ayl5NGV8Pfn*_=nb$lZ zS|%TOOoSLyy_UpdgU}fKp@f-x4={sR0z8lx;XIjnPnb8Vy~=PkYK;gO0^Sv=rMY5o z-u?>o2@ax0p19^UjeDwLx&|yL1+~sGs%CvyQJMxOlw+gQ@rgAUcN{)sKG#s`knxLf z*bh&a5#=mPMQFStsXu(*NE4n2>PK^il3qiD!P*)f!ahm{mre@(0}H_YLNqRT*)9Ra z)R+Xx*%~2zod(m9pW$wSXH*EP#brz+&`iz}eeu|?4i8pqfX!bl?8>^|WP%FKBH0zr z_JNF1Qo1F%4WVwrg%y!rsTIG}rU#E}$F#yJnRYzjfy0%@zBI)f)7ETP?rSzXpf^>( z?!0KAQ!h@W0QPy@P#<-F(&ZXL#^Z$)MJfh&Y;yd*wn1KgythmpY%@S69t%aMaRRd3 z?r<5(0(ZG;l)z6QS+mKl>N8tbW?Ge6 zDL<$g)z@l})ofyeObfB_K&u0@Obndtv25Q}C!_9+RYYP%247dQ4MK$1`ge(_{pPbXK zImd~5{Ts?ZtU@$+_B@+9Bi~OnMw?CVM4q~CCS0mANV8O+a+2*Q;ZS4nYBm^<>#k*; z%l3lj8n1_h;e`mDsWYe#vZd4W^<&U52cH#n-S;i%XwR_7hFd|yt_>2g2II307hC6L zkXUButlDP_@0$m-V+RULU6LVkh!8c0sSI%z5jjYRE}aEHnMYBHf~%0So(S|Nyn4no3tOvxb z=H5?DH4(HX0_#`hzD((e&}=O0$rST!lF~vuk6m_un4U@*uvf*fGl+_MAp9*5mH9{L zBZZ1%j_vR2VqxpDVO`ibe@}6CjfHu1ADnZxzCD_e&3)b6B!;bxbsO!+yT|eFCX63HuGuSChuC~M7*V^!XmLYpK z)&(fJFAa(jL$C)tSqUZPfNGt(ldr^j5Ll7!^ynH2?gmAMDt80qDIywmNiOs(6;Gw0 z6D^7|ub^H5^M4t_zz1wPJLgC#rNSr!#T%hYMJ#S~bhINb?I)q|fkcAP}g{gv7pi`+w$|ep*XttSXjT>?f6xh2@l~G5Xkh!j$aGcEFQRx=gz{ zp*#~gHJul<1x80@j)88GB_3EMAgceP#EVltglhB-#9GzlmW;u!npQX@vo048e(ZvOKRx|`d!Aj~gNOFr! zAiC@HKoR$t2u!Jv+i&OL-!}r$4W$>4h=mHEm4QSMJbH>^us;;oZ|ze0=C(Ql zo4o{-$7votO6)6yOc9*s_xH>MdM{lVW(GvF=l|v5IaG9D4jj#|l6p|a(?sHE_u?XW z`TCm&yd|@|8za%{${DVZGLOlC6`B$yY8nd_9 z>^cLh=j0{bCo^i$=FiGrRpmd;{fWAt5v;5ntS`ORUdXaqF|)==d{C^4dQa<^DK>R8 z?m3H?sT!=W?boN%l@Sd8GtfucRJT_|SJTpMzE5sgmf2x4yIeya0Lju2Q2V!+J6`*v zt22wvIJ2&yd)I8X|H86znA`6jThr%uGrA5>7=K3n+Qw_Z^Cr1ohM$}GkE^cN!R1e? ze!I{8a$Es~IWhCR`RG_{@7Ke%ZmPP!@%7$FFGu}{HTBQD^XF%8n%^yd@9}ZZ0O?AY z=~MT7wSCBs+4M5J*3Qpxv;M{J;{iVY`(1J_e}?zN>(k`A^Q;AgyU$wB#k$Ku=gu$2 z=S$shwYwZB{?C~?y#Ln+duk7}WRCx}W$km~yuZcOP50YPGQF<%?>RF+?{nem4#%B* zuMgwr2==Y-{Oi`^ERSEh&s(*-yf2FHXU6Zf@DDz3%fYC>mCt+^r~kD6GoH7>eKEg} z*~hV|zhzhF_4jX7i#EQ_^;^F)zt6XK&-ty-l>Xaz+gJ>m63wnA99_pKely?Z<;N+_ z9Nuba9MHAH`{-Y>t!6ZZUg|`Uf|_W^rs3<-fR61S#5_9nAA~vZRDXa)_vY^DNP@d_ z`C_vzxkA_`dw^EE)ihIfrLK3{6;uJMO!gvQuSZwm+3<14kV{I_nmW_|!(Piz=(+2yG?c&msiix%#&WVh;p25S8(7*30 z9W$6AjOUQZ!E!25bBvP`&= z>3b7WYp}-j`n~L5JkaTSnH<4~a~AUYUvQ3ItkUdU<;fY56N=X7Rkg(N(uU+F&SRUf z?_9u(bJC;D*&H_)rhFX}r*nf}^kLU;&J!uV6nMgpNowP&Q@)Z^x_J9qt*uCVQU#`4 zTJaT%bVohYB(EJyVwle1s+0Rq4zN_60Bhvuu<(H)BVoot8wa6WBQL(NF8Z&4kLnlk{p`@{&~3Os-B0tI`vL3y?J)ar z>ySU%ujp6)ThCkUTkQetJ;?p&0quS7P;L}I@~`%n{(Z|^y;>=u>>N*q`k+=2nKh7Y z{z?(;LI$g-c1`utij}Qa=SqI{Vn;KcZDNZi_EKmQqHQYL;)~U1v+zb*%7RRFS#s0< zZul$5%`edZ#u9#nR03|KT?OulT>AO`M?hAOlRu?KkR( zIlX0Vrz`eVo1i5IAyydNN?#K0}le-^I;+5}NOwHA9%QXZ{PideST#GorlkAoWmU4ZdJ0#~1 z)?ip?I$KPkb`SCBUw#(6{KV1xt15SG0t0JuNF3PD$O;0AvmhkE+~5jTE6gK$#^10UR9TVK-B0XUeh`t-qPQLTo;p!?#=DM|J#Ml6o29p5CDJz z3;@9VKe_NfSjPDgp2@_(K-Iy?^~sfHeAd*!;0)Br?&WByAYrOW=H*BPp;7}d5l1gE z4F>JdhoJ*jEXkQZe!pIxtRqnWmb7&Am85dB^_8@cwe&XC)#TH%RFE~)>IZovW{t?;%-mx`<5S4%|t@Ibp5j+E|2o1O%00KG%+72JCi2-H?#Q;gk z$Ut=m5Jg?<4-NoS3Q&U-_RD~io0b4Y2~-9I22evY zH^v7r9D?RCWC~Cp0w*e&8Jgt<1xiN>3BWx~(E{el2-txcnUlbQ)CkN#jKl~|07h~w zY>C!j8nxgm_}nTvuoGqh8N;Ba%8apJQNWevK;`DM^c3S$v(%x`b;qeGMJ8yb z%pB)oXr*YVm*z!gC#vTVD97f-WFW@#y(GlV61^0xl=Wj8{Cwps%;ci{q^z{{ETtm+ zQiBgOGkU$|I4H1mYnf=L3(oByD&Qi)sjeUHSAXuPJQfwfV z={bLM2qmJ6NtoGLgJ>Z!s$P-Xk&cl?k=Bu``*&z&=xL?orp@k(r@)3q#~E7i7(h%I z892yLQvri(<(vQv$9z<0FY+8XBQ+FBS%Pm6D8VZN26`-TkRx8n8}Z zM`o2Gyh_X7wbdSZ9s|or&PnfWB<{bl(6>A1WVMi683WVv8bmW!MHrs!o!-mYu;;&e zvQ3csjynFiT3&$3_cyXqaoPs-v`6<^jZcxXj=?H}=H{K?68Dl_)ek@IN(cOEecwmH z3AC6@bxhl=AQ|}AT3sH)#3 zMJyB%7a>*RRwnl1n-8L4zF!NKLABY%RjrI})@8OPUW>>1%^pYRCA4#Xwpx7sJEVJW zm)qN-q3i4AO?^Lv_f30K{S|Meb!qPXN{8ho>&f0KXZ>I0j#=Zt*bSzcfvZWk+S;C8 zrG#hKQTKmxoA0KI2iCN%sZrRLUO!g*k;lD1GG3Z*;07~y<5M8X(C09J`XHy7qlJ*s z?TVbP7y*F)9d3>A+-%uLP=LS#D1hky5N>@3Q``SJ?VRcUC*?9prV2Q74b_hB?yq~G z;H?CLApJp|VD6Bhf9(3V2mA8+A#d2)!11&CA>8$5x=&TNb-z_>wK^+1{jWBla`_(n z33Z_+Cnn3rJvuo0`}@bgKrm+)HntacMs}8#H_rJNK(2qGWysN~Yin0ZUS`T%PlCS=nRQMBoft>Sy{($`a zT7Y`){+1hl&UXDiWTuQ0i#1p=Ce06la zvqFe{zR-sT*dHWE!a=Le?z_#E4dqa^ZbOJEEc zwwa93VDWo>4EcoiE0jEY<1M(Y%5FYJEK~OE2|7kej~l?s6~bJGgI@rUBqIjt)Zes6 z%(+YAy}(MnLuKrgYw4FeMvQ4jo_SYmjqt7;Ll(xj+#(gLN=S`3Tf=+O7HI}jJmR!3 zX9U;%a^TUH3Bpm)HtE6LOshC;BCU4!LuygHGHQKiy9RY<%|VMFEe~3blB4oU-=*-1eqI?^30aXJ1NLXvWh8 zT+@`$g)L!y>55~o-Rk9`gD2tC1wQ6&8)I3%YlVr=C#keeQyv7yeS>JzmV}eB43-0$ zqU4MgXJ!@5zg*W*Ce^UJ-K4Q@ZrFxb@=Hg}f1rCL$ZXh&ST9nzvfu_IQDU8Dn)X#p zF+nHgNRm0GMZ>ovsj*2Og$X~%FEkB9yZ9Y3-7d=jnu$PTz(v6YJcliV$OtEkL zueAK^*)+Tq{2hT-H}ZL8%e%1jCl1_tw#-rLZs-a1^=xL%hi|nUR=g+{-h+!#=)JW; zi7S*J>o;ne!*1_A2J%?bwivR7HW*?~(CGLaQop3r6t8VEP&oSiF)<2aF=ii9mnArU zL=PsdJ21{Nt<#0nt;e6f7;b{oOpWb)+6>U+?ahQq<(PO2dDAwL4>Y9GR{{u|&~>iU z^N=J{P!ijhLRY;#(lW2W0_!P2jd55(HFcuTPOARZt> zWPle$sX4W&(lYlrR8YbQcQjbS;RoXZ%iT#$rfz4+SVnSSi4g{-Z=2qgG{R-Xr}8=- z(7N@LnxqBeWwxUZVY6wR{q4OvsyN{DbLE^-t~^iw+|)Rqq>&{%Wf?)ZnV4U6wdiEE zkY(lL_5cqjFvwev^3@fxgKA0o5KFA{O7pTbCCMEnHF(}9qN3d`5$>`BX4=lviGC<2 zXQh95o0EAXMsy13=ld47F#P`HY6kI(G3F(ibjVs;qZw5kt;vo?Pyr`LvXx-$Q>erd z6L+$Vdq;{FrmEA$$uF^;B(EwAg83j@lJH5BlkNWv+s8d$wQvb>bWA|ONw07ODz8ha3*i#Fv3)atF!i%0W6IA{$f_W(gIp{SJD1Kh=&MHiaIR3dcl>v>4vK1_| z12tX6=)vwv4;TpZ4yXzg%xs60NCr;Uf@iv$u(?m|%9F?GOYFf652=h&OOJfW)SL){ zA(P8jma*LGd{{pZn&;PMj?rwvzi&`z(ap+QTLYKNL>D5w(C@e{B2(WjQ*vLs5mY)= znO}hULsl-GvL#2xw(`o_{7nfSH|h2T(a>6(9H=wJdIUcm9(q=^gL+n>`cBfW6YgJF z*a-!k12e|NfW!aH_eo@GP@$Z|i)@ z=BnewBINHu&+gp^8_Qvr#je9pJdWf8kj0If#$=_=OELGN(4uPQ|DOL)WHdwf=s634 zjlNdUx;c-#z`(a@`0Qp0y+~u{F8~MyE7wa+((uuC3IziT5$M@J5W&S!jhdJpJXeM0`vfU~)Cn%X41FP?^|0z- z6_OgXr#^t%%$xoaZC;VW8OrLs+*?)3(I(DGTu`>AG=Q&vU{ULPR8Xfh zETz3YToshy$Je*{G{!P_pdz6dMeab$IAsA1x#*ed3?(T^?O+S4axDet%MWi{Q$t|M zbdh2QY!|9yOx6L9rhW?}c5>xjJ&6`0S^e4^oUL6j0T$&EXU+hD8ZV>yViL z7&?ujgE!0Br~3`la;krOtQOLaJ@S#vQ^|Y|=HI#kO^<7QrzO%j3+n$c2uKXuFWmB)K$4uXI!36+P|7W0eav43y#sXo$Cw|`zkK?8@O)j!$F0M*6U z6s7fW-oCa+_9|oO3F4G1#mp+IIzlmh6K6$u;Q0ibjO{N38%;?!wZi2{)U0N@Oz~6Dvhq!4j_E@NK@_bL*RI?<$2PBBM^B z^S<9$s2R531?i1j4Rj{*0Qjqsvg@|QXh!xf+ln3s7g4s1;bcIrsG*VG#vz0$UOVe* zhcb=r4; zU|_#ha3Z~=;Xq`I;3GyR#x5QWYM+wj^LeaEpb6LCXRS~%w)RkgJc~1>RiSmMm3K4r z5BL3jEgtLh^*>A&adS%oVR9duZ75l#>n0`O{v_*rFIkn~^y!2DwRnp_u|B7p+*L)@ zX6N^iA~DECE>vkRd`kCY*sKnO{X)E$JD_x7nSNTOwL5z3?z@fusBPecLo5eZq}|w~ zjO}GT_zIdUPdP5*GEet{1v_jlo^Pe+rGHsM(=bTb_Tad%(yb7ncp_zGiJJ72`iqo1{t?fX zLYlAeM~iEKugnHI#~SJ3eB3+G8yusFn<;G3W*TIc3>GUE9v6|VRv}k;E>~Vsk9-cK z)PkO`Ugrv9rx9uAR9cV+A+VbtLRk7_K8T(%!R&}9yI`!Ol=7Po-yH}7LU9cuz9;$a z)4XB9Yma@9^?SH1}dW7?_{=M;vFAA#E{_1K?DCP#jv!|ZgYPGgWRV#a)s0vnSP`g zP+!QhYjz`H71j->8R}Am-M&sW+$>S*R{j&?^L*aP6UsKUk~lsEb5+9gjqy3;Zol0$P6xj z^pEt437x!=o$#{EzeQIN{qi zPYPxOKP({>WM4JMVBc;2`T)s*a=Bms|m>Vd607a$Pv^mh| zX5x(=CLYt%zsd3%1lWBJoiQiiR|Yl&U_Fauo_Q@2iPblc4{F8f1R|gd9&x&3kkqr4 z^49(@w#WUn2$coXxiv{)n<6n%%yi@JqJM<_4zEam=O-K}{%9~F1iKP>Erh+it{vU} zO_T*ke~g}okQcERCWQJz%%O~V0@!=t*p-8U z)f;y2I>zUz{$b0))ruVbJ+oW?QM~cd~Oo9{d4=(eAOUv8l&n1 z&pHx;`-d6J3CbcCGX&K)&wGAJ&#$YN0y?0GQR$?eCFxw$cA6i-AISoj)Rym8&!1(S zmXxUvV~(~6DazkTvbC*3O%GDq8zRNNX5A_qnOEfc-X;Pj`XJ#h>p7km&VPsrr#=Yy zmh4If(+@RE38qOZjyudK7#a`%gcY5l)Ht&t-%{BwGhwSOEi;%)aZ&@UME-~X%;lmL zZP_K=mt39rme=A*2`aqRTiP7Nx z3tk6a&$kY!y{s5r3*OwY+B5C2?&9a=Lomx;KNrr$a^Zum{hh&^@kvH95ZoCwp1VsNTS?NMm4c{L%S<$u;-hl|dUsNQ0 zm&P#A!+_JeC6^S~zt4L^QZ}X8#`MzYKuYgAN?X6;l8-!Yn`yCDobYR5DH-><7*y*! zYp-~MwHDQ&-7Wb@=nvbrPjJyJbhmTH!r`$^5|PE^TG;33uJi4>@oV!M(e^qUkH>#- z(7t>o>~8QZ7CjL&zmj3bxdg|AMGP>(wVEn?&5JgO20y&Viy2qVLGgE7XAy`Uf+56c zEwd8jb;r%+cAQE(@}OY~&3D>M7{y375UPB`g=P|MJd8*kpYNBStkW|g*ATMhWetQV zB%VHWjP{J+Q+xhhSXKyUY10T zM|2~IU;&N@UxS;)V55y8E<3qWGXIm_pO%muqF{)$baA}!)Ql8tDZDD1+cE@5{*nZy z{gyKp=Fbdda;VXN)IS;%ubo=(S6xkDC^GMwN8}H3Xa;ZZn!V&ImfVtK1Vh3xXHgqK zF`w?4s|0P7;xWuDNwBKme&mFz@sB{7X1bEmOw$a`Ydp*)w-_WckS`^&BiYIu9-&_TY*Nf;){V8zlt+VOiS0CfTv9zMYVxdti`alOW zA*{T#OQ!X76x|dN+ZGzkTXmNt9W0v!ZNY~eK!NgSQg#@%>F`RR&>{xPn}oErde{o$ zs*?=wyuw<{Vr@I&DjGk8TsIzteWj z&~qqhX)t89v|EUM)Xf$3@v(qXqtoreL}f{IF_BylZB{uJXZ11+|v^fKq&CPU+6d0 zHwb0+{9RwdP-+>Qg?Zi#F;0nYGe& zU@(#bes1HlGI{Z*5Sb3)}XRw`S$LXu5%^Hl@Y}zG4?$FOJ$S2G8xXQ+ zAQNQqh%~o5)=ZT_?>Bi%oH0eSn)uy4R0@QU>pkwn`5kW9Z8t$VNBOg*+rWkcXfh@B zE0pyG%J;3x0fTvmJTcw{gRI_m-#&v{v&3nFgH;-=;FZR+lk@5xZNU+EnIy`{ot7=M zD$h0~HXH^kWa!i~1)0Jwje(Z(#Lea?ja7a+$Pe;`K$|xGL+rmInnj3XZXHKrI|(n$ zYO6-mkJ8v!e4R%qE*gwIBpRL2Y9!PV|8io6(z>MHw4hqcO%0HY_66MV7vL^0vDBv7>IAobX9~OmsUS0CdmD{Y z@4?-&t~O)+bGVct9nbF1l}@iwz&Wban61r12YSvJ9ps1)s##9)xF?QjA`W)SFOl`F zO>LehuP~R~R!@7zUOdyrdqY)2d~h@QHUo&Zd1wjZRjAOs)A~i_hW)d3`fP55>jvvE zx^EJZ=pocWx?Afz<1UB^CuLKShpRu<@tv)==T;lPv0T@g{w)i37j;Y2M|$$4b>N6>o z?Np|m;lX8g+D`=L1%XQ}AMmImzfnyaMfJDrc0`o5KlZac62TSB>*n7;6tgK&-z_yU zaLm;z0g7ahuq=+M@f`fTG&2|*Pj>nmq@iP`#~Ir-2D*^nRpG{t4KGNDYb_5((>Nq)0_AWAX7t%m&?9f& zCF2isfu?a`w-7#Qs`ULCfZJGr3H4vd;@uyughgCcLh`TK()(vU%*xe?adD&lix@D% zm6+FooH^XSGs`X>%XnT}Nf$sxhOY#r+-dkTCX5UTSz>otTb_3_AO0h`X=FaA%;9Gn zA&GDez5EJ<$^tEcS1=MBT~w&U+}gn$SyeUs?bX{1d2*E*hW*Z6Tl$kX?MnLR0wGyg1 zY(Q$u0fou@t6CHpU})}?D^1=-uQXjjV5&7Zz_9?Y{ zYbFbG=et+8>SC!; z>{8n2a3CK)%jI_dapLG*`Fu*1o;GV4P@-i)Aj@K`9gu2H?E3LIhicH-CdrslA<5FH zf=MqJ(zqgazQi4KmX$W@P=B|GiET2k39W8KaSh<8A2A_{JRptv0VZsnz|hk;60Q|n z_@idc!tlSGx?tAK+Ca_ND1)(@L8YoA7w2Z3-aKE>O7H^yHJAYnvir>p!!LFa8QfvpJwW&b`$Sbux2RF z4lMOk4izljwksZ4^xWRl_CJ#ijq0Tj#y!|=@sT2Ur2{q=r?4>`YdAe<%IZ|tt4teW z1)MxW^~G^AY-j>fgP9_AKDU}j!Uu>O0OHSY-DP@_v{d}Y9azE1%6%WLY#%h1Ry3Y1 z)D6b1?=riYW@TlR?&)Q#;wtl^i<2`xBGyik9R@e)!qO#(rc+10^>jZ(@F3U3-b5I z^Xxxp(2;MirQIkO-a0TYYDzguUzglMW9ExF1!r%SG;+lg^_QG-EN{H|V9!hw5KrC{ z!w>`b=d0oZ??@rjJW9WMH0(JrV5L<4GE(}Ru06VK84#du?(r-ruSSha5P`xpERVz% zAZCAhb2Hv&&p{Q(j0xXE_=G$y*`aQcrksB5k-yXt?C}{A=ywd&ywArp9!X;=Lmr%! zf%kxrRW5(yWN4CRBEOf#H*%)i_HmFsL4=>38_xKs28er{5WXZQoo?2;N)4RBMT;Bj zZL`wQrmb>OHX=59p);kLT;874ut34jT|F$e@#hkW;`yAUx#(%6FuoU;_wgenE)4)Y zhQoN@Jo*oE$_j_H2r*Uqf>p80)D!9V5HyzfH zOehnBXxel?xvP&XOJ7c#)Dz1d&GnP*>~u7&oemzo0(L`Gu*LjD(xxrXC=K4U;Ge)6 zOoooPs*t+*`Z$;(ZgHVskXC746UOPBFQBRl5~K&4>@6@bHyVkrF?XEw0(5Ix#k5f= zl<6S*xSaIQu7vMZmVj2msBbkimNHMAsFnDN!uh+2&E^XseZF=EA@$IAG?g&)T>w&x z;NKstCNh`A=;eD`6C!5$?&Q~uj-VChNw0*|=-tmpi#))DLfMQ+A2ch`qAS*X#daul z4JCfU`TwBp1P|hIJ$&ew@cPIPXK=dH08OY=W(GC)&tjofP4uF0)oZS%An8ikA7v%P zte)82ei^boaRzEjl~z})+2l_hUzN#reSPH8C?rP^r4%z4a%ddHcCVT&m>6;mlnbtG zIn2>30~IcS`AP!BPP>%O}(7!x+6fj+g!uR2l#>Lj(h%NWlBf1vg9ifOAiyJCH) z6`^*5{Y4#v+BBk)Q(UGr$>>YC59x*H&o0eXKc%YYND)IH~L0gkLch`+A4wfyk5<53>6DaP}%{Xa){o9yxii6@r=N_K0rMmQVAe>L}q)z9+}F@cteWdD^P+=3fo9m$n;Rb5N{0muzvX-b1A5>GesC61Zur<6IifbVk1f zrYR7DM=H064V4cG^*ZIiMuyOas zTu#2%8yqSFni6!-Kgoze?cb?+_I$Y&sJ}S28M7S#w>^%i>pHhv7Y?Q8aGLR+1VaHtn*#EGgpd zw2h`_mNkYW22a0$UvTHsfcE!L&O2@GaL1aU`}+WQNHol?Lb;wEt^z?D!PZ~SslU1I zXBZt!J%c)226RXM&m$bWAlVAE`}iU$zp7~<`YgZ5X{l6?-S7k-kS9IbL%FblcF*b! zU*vg_Y(I;3=S*yvL@Hq<485{J* zoi`4LE$3L&y@Zf%KrC<8Kh}GdG}qeQfSdvm?9$zCLtm2EGu|>p=8f*r=O=ycBJ*Nx zB(A$!3cmKcQBlxc@=`5*nF zsx^78el2|;AL5^3I?pM`XZF)0CG1!?xhml>SFW{ z^jw`kI;_B7YHS53|NOtaP9O5VoW9V+&(wWuaV)oJd16D@+~9I`+%Y8e!pBvftpMS9`2q2&vjJJ#&n4C9+e!L z_n9b#j5lVUY;_!>%)qd~@Mi~2xbPfop5LKYe~7m zfTx?O6}bc#j~5=yGWg>5l{sV`R%u7xZ0>KMcns~3SD*#7s>#}>m0Nhh^O?M;TqeBU zCv{f~(br&|=7;r@k;9}5!~(e8Me#ldn)x4nYlsVeb}$M#qjHFN<)N_pFPq!i*_0b5 z4OMNCkCHhypHr)Ik;<`>EJulS`wB9@+qQ2{RXXnE?ZP~tZ*ZGQDhb2 z-W3>oLqLrX-RzuxH!CIOA++H0w28+3P4P-fG|Ac{xh^*THj?WMlQee)Cl6yeL5qVX zl;r;HB5k~*(|FaWgqXLWng0xEsS3?EX}qo%$;J1;Cp&p&05DIs&}S3H5DDZs zRf~BcJ*HHfm}|pR>dyK@6AMV>*lZoCcMg#NsXQBmV)>s5>lDuGE^1x2)z}l}gO@QB z!i8dDrbJrid6sqbHGPB?533arf8CDja7W2mi8Lry^LJLB)*XN%l1R>(^;n*$6et{} z?W8b%6}N2!TN$jH&Od~Tg$vg5(nT2H_29=9YF4Lg&yTH1MXNyjt7Rr8HEb~5(k$#B zl;yD_YT32WVO_tnb`C8 zD#jExEV!uR?D4i2r9X?ok0J<$^nM>b?Pkg&+FP!C_#1_~H}Y?)#ec;m-$g@jGMU$| zRpV}EZKhUa*m9+L^AcYmaP^m`jOk`vtlOTqG&lWvnAq>jSTIP)3dFR3tf8MfTr&_p ztG`d(FEyAeu~>&Bm2w%sn*iE2`rlGE-T0g%!&#OHHeip*c$ETOL#*60HzcGdqaHD? zf_gx$uOjE;+8`DEg4!uSBIhX~o0K|hPp-jUWhF;UzH_TJ4Miyl$v8NOMuQ#VI@F5O zt1+yFyyPif*S8mvwNB&0Sm|Mn+D;vPQ8v&pmqR>BOkOcNPQpVCeS94XiJAzdc2@F_ zZa9a>w#HwxYI7h3D*J{xt85BpFW!CF4xSn({uG?z9`LMH&DO~&KEn0&5IQAi{&j_9 zh&b?P3y4%4(78l`ikaF3Ysv}O%DJvQvD4ct7I=3gm#4(8?9tA@Y)x2s)!1>9BU^PY zHP>7U&33?WYVQa8Vrj>jb>d6M4y*jvaelja-$8zk0YA7O(U-u^(&Vq%n1*#luX#f> z+(myZ$A4t_GUj9ilB>~gJQB^;IodFTq?j(5HGXt>ABW04LKla)f_1?m9emmPVG8Kf z@65@2Wvu29%HZ)j2pxv62$gH{w@>EN7wUph_f^%$2FnyiHRYj7vjqvFXE|GoFNN9M zVVI>Um~^L1ubdgT8j}2GbZBO{_wkYPI0LWXvY8|Z9ba>lQhJ2R_uvEx=#v;u8*ZFh zqi4pHmyP=cbfi+fruU+9SCU4LOZr|=&C?)2bRC=MjLuPYx3TB6;k2T5EMsfncE~H5 z?J4D=Q2KMh*^om;=G>4-XJ>V*VoLi@r$DlhYbq|caHom@cX?{@q{zZ^4&J$3ln4X6 ze=tP_c*6hdYTiR*XV~;{pcDz*Ldd8p5_5kZ;-BJW6!!)ceBzCM%RXj&qq3YniLj)T zOJ2iZnX=xv9shh4z}4o9`-vLoUfiXg%6vI|UH(PI|Mc9ok{J?h9CoKV3^TjeACby< zXJiKPxn#Om*?60nvLHK{(XZcON5!plc`h!f#*YKhhdscL8-7DC3x$zJxT1lKcTs|J z^>~m73}0`MIzXvZin3S~;vEO$KJhZw-bzNC95Ws}F=HjU=1(fsZE?x!3HVeln+ZyH z=jA?Smrf{G{=Wb~K)=5xrSX`9x3TN4*G8=wfpwf`gal?MPBzi61*Fq_=lY7v&cMS$ zsI1OLVmjX=Ql!eba!$12YUz_QU)m)Z9_CEcu1ugtz2k}0*eXiktl(c|dx{+Z_NPur zU>6~Ik}0AEhAV{r8ck4d6;h9p?4@HbE&d1ndNf2F&Fb{coA70Ybjoc>op>V zYfI+0Ou@BUwQs4JNsl?!quiNor57l*b#ik(N5igX95yWpQV4RAWvvIOx_MuixlO#e zI(?-pV0Cf+jA}nU*utiOtSj0wcwSzMTd_1x9$>B~wO8%mk-cgd;;P5V(jaI{?n5lUbc=pTyy|GwoYd`hFxpetU_D* zKD-7m<+1OeJ;Id&;z?Rwb^C4sqv5$h-!y1jk=k>>Qt09La*&rB-fYIs3|-Ar>ix#K z+(Vq08t((wqUs8-&w8pSJfIJm?BsjQ$A?}G=X&jVCz79K6f#Kja`Z{5K=F!9R_|fY zn~{#Mxv6EJUa{MVfX)*r7L1EEA4DTMy#%Q>Zo@%B?A$dSgr_}szO0%?O3jLE@pw8zqwUlgf0Ouq6*?OHn4n59|iLfWbyuKAEK5!EJh zqb~pKDH!29p!};;}7d3#7^w9yXPk({;L4{(<}K2VDBsW7arL&>l{o0y2;*e@SzjD`>7TvS8qL$2r8{o^Hw}p zJkAXHGl}*V9$Jck3L;=)ng#ZHN84p(1Umkow7Ol$?jNw1nUE+NFj^>py^YK*K30Rn^yUUFnoE9eK z;2MngaeGa8!(#E7_O7oGB~WX z`UqH*%94TXg8uMVXGMEbXED407PhEKE6b<#u2I5*bNjXwVyf`Zwi_xizNUskAOSk3 zCE{MjOuD`>U7XIRPK<=s$^hhQ>91l0{n@Mk5$0{f8{W378%vm zt}=q-p%Zl+?FJ&{NGeTyt9~#7m5!)CIv4nU@*fDk;xE8Pff+30V+wHkdKr2t>!sm# zuQklG&kU`f;TA`R+`0HvJ7z0`iq12>Dl|yswj4mtEL5GkYc@9npq8hmhUU3{O7UPW zLWzGcdnK0g3O(ItnANpaufmysjJdU%_9V)mrFQ{F^ z;zV(}K7J{;-K>+mj^N5G#2Oj^k=lk%{TbjXt zTPn=|J7mjLdimms`{QxfJ9p{3s~|zXiK5RG;z2NV(cZgF?b=Czd|m#|*Bx^u z2QJ`7Ou0_fy_BHB(eCv87~?UrvNo+ZPk|@_+Q1;GoU7w8FCs{DEjUocB)1niO8SEU z5<|%7*(Ln-LbJ6m=jSd|Wh~rwTC6kZp=3P51ZNMmR zxkf{o>Bp%}w1IZoc;0VAM&I4_yf4J7nmDgPfb7FA49#ft$7xZ8AvV?a*a@9 zcot9LWt^`(r-X3Cf_9Oz$t5L}p|1-t%XY~EP2@5fQ87IDtV<&|x`GSPgqOrL^3$0V zCD!&FG@x(J`R`twIpySkTFwoFD>TQ^37;9TUbLvR>)Z z_u5e<&YOx6Gh-6xMv<`?Cc6vlhsIoik9YfQWuQzRnLR{bQ^p6zObBiSg@(u1Q{ONJ zyE|>4kKT+5in!Hu*~YvDOBduS^jEBPyK-W^F%2m9D%jjL1ny)(hp7CJH8RifCflwv z;h@^)-90-iQiL5Y=-J&v26mwK)y1RNIpHUpDK-zfY1$ZT^*evHoBdC{x_kLqJ3e18%pWY;=?N`cO0zAc~$wQ|82J za_(B@au`ORYvEB%gmpgx0%*5s;Q$tvV{O$usU|ux*h4u0R zc}3BjZYMNQV9sp%xdzF-PJ|mS=@-xz&{($&0cF?+9B_vt=PhF$iP?+|?2#GCVCy@ZV%5ZZxh4}u1BbUsBVC0dc{ z@(if}es?KfNc$lW=^(E?!nK=5qhpB1nC}$kYGCr&eDp63(4X;RO4=t;pY9jr9I{3n z$ZJ+X&$XXm!V#*6E>!z-fRd!FR$kuN$zo5^RgE|el z_B~sT;f8te>`*!875kMu)*D)l(AZoSjSqwdVR_jDs@BZ9*A4DitVfbP5TNWuRCZ*8 z6^rYXv+dxXlNV!g?Q%TjvIZfF$XBdNH-(};NPsiJdq33jdRL!e6A8WWFhTO!IP0Q6 z;I#{lw%KS5T431B$gF!(QK5~f`v@%p$&3+Tc}$9_hkut<@-FG1j&n{&oM1njV`SaA zbUcYu4D)p8#QnSqQMJw1O~3UyXx*o|0b*&@bFafgdAsPN|J=}ETBF0v-OXT$S=7P4 zQ71tYkW+PTFTu&G#m8{o!N>BC{Biu@kFCG+$Jc+yAOBQ&^q2nlFQbj}chSc6j~>eL zchSZlUJdZ$<@|Uxhrj)^h=cizIK+3v@h;zEc9&P^&Ax0%x~_udW@qTs%5X2H@$bUc)!*eqeV@x=8T0} z&x!q*c>&}?hvgCFl1OTIk<;vD+2D*X@?1R(U%LZoCN^{BSV!e61|Hf_d1Urb=po!?ks-S=ob9wPdUwqGKEQ|Co8=1ebm%19 z^^s+wuG&k?K9B~8d2H0DTQc@bTXnrji;2e`?i63X590g0+)!hGxq zy^cV6S(NDTR5c-HHcY+>Ckvv;FOEXFT1x!&okl&H4NUU*`}Sh%VfrGc^y z1C$XC`>`ps3+ZU-x~tVmrRn3=hx&kck!-wcY~F)>DJ{Ynzt6G*f1Qvr5d!v$)5}0k zAanNxX}#DxWbU~k@1OZ7;D=quzdHH%TcJVlyB+IqY4(FiLQJm@eMd5CifgdlaeNsV zSChf~;z=VVv1zp7gJ<1OJCOR--dg0C&lI%H!y*D?#j*hz?ayd zC1D9_i-9jl`5I|r*RBR|xZY`{%?O?H5VJ4BE*sr>!?{-;EZH@5lI;YjUq~Ez`B6lwe7K#q22x02_92=cLcXY~5FM4?LOZ#4f`y1u>PLM&2@FKM|d&>s{e@d2ljQ6{~#2 z7GB60?|{I%+m0o@f~aM|BV5Unek+zl6LPK8G$AaWd{e=1u=7|uChrK-gRsoY(ECI0 z8lnNP0F zBPHokEZ|z5bc>W$MyJc4NJz3*B#EB7LUGT|@XoJZ675GnKhK)wgbv|6Z#TDEe85mC zNxoT1R24RI+BMhp*L5zt_OYtn$TdES&tA1hS3KUX%zEl`(Sz#PP~g-yPY>&#WdGWC z_OE??-;m|70JcpCq-TXbc@7VUR1*B*hAiFx+5!0XjM}%p!?$PT+^V(>o10bUd%aHM zHuWC7w@aVq`&nP-&j*jZ^Kbn7i7oF^llK$nwLM0(?psODdS$8T`xC+8uuBjw4;^g= zVh^s9Myr4BwG|hw6p`ca^~S2m_kEC3JRCc7XZ>QYt7sho*b?^#_%@rNXC(cVhGfmv@8%p5`FeH+-&`NMP7;GTo-eb#AWoa9pb1Mum5+H_n zClKDvaKal2guD75RlDlm-RJCm_WIWQ4|-J4W2k_0G=tDex_t%8E*3Yx%Stc}ezT()+q89BosihO^o^z6+hf7VZuAO|YZ@k0= zcE%cE*c_ASOiRMZ_WdQ8wi>@@ju-ISSy!2v5A;)oNV|MJlsR^PmC!vFlwwL^{RCX; zyOA>PKtkA4mo3nCCc5H?G9lTjX5`(toOS{n_PzF$Q3+)TUdhfEq*V;knjceum`^GR z5@euwYgU9SY{tf&mM*c-`Y4XwZ{e_97v~~40oPg-3JdfrFd~Al6*bY51pq-d4j(E- z#i#bFJxm`zAT5kMIu<5RhATi_1oc#Z!6>$si91vWNLe(=m zRE9*fHX_XYaLs)^5ZQkjC}H35^dcHXy zVq>|MG%g93SG=7+v7D$j<9u*fA+bfXz}JQci&}kTXT2l3sJb^_@>TYqul>Io!9QVE z#n;6mZ2Popa&ivz8sdOT0I5SCN**GfTk@K`7CIRt_L3UR1+IEV$E(rt z>0Cc=0V88_daV_&2Qt0bjnk_RVm9#9y@-Vn>~vN38@DPnuP30}dadYwycic$SzlGy zL^XGYPiz!bXF&p-YdSTxBwxtP%@>5W2>KC0)rCD_WryB5!V2#k6X*;FEd!tQdk>xo z$4BGWx$&dn1>9nyt`Ga&#OV!(9<7H%igN&Cc8ol?;9n%zv=1u|?wD&6#)B`fgRVp_ zQ}H+oNlp$>%Fr`77Zrw(tXx>-eThm>@dZ5w!Se}SvvzlyhLnW!o#!nSC!2X6Q3-jB zF**bUAiCeEQPel<&7acx{ur(RUef7CfQj=Oq1VV+R(v%u{h@I213gRr-9p5SDZn5% z0`Ya8b8|vDCgDRI2UKdVZAsHf~2P2dhksrXs=76q4DT-Q?BB&!4(g- z@)gAkTq!h002io7dv+B=*Pdl*k8}}?$-k2?ocd7^|M+k25#krCOEfAj2EOHI9DBnu zPjd544^B#23p}if1b2T|(SGV?a#$p(9e8USpX6FK`vnlbrlGJj&&DV+hr;Efg60#M zT=CT*%2CS_9D|`hw`Br8`Z9etg53Q_+=F{3*)5;q9%t2-_V+){u92JDFWLS}QJM)$ zpW49WDp#jl=<#sqOS$dwuK+EYae~W+#%&=mi2m5%rCzS< zX1|^*9}%!C_ZBm1_*iNAd3wn1T`fIb&w!H(&G|VhE7{aLwAxyk77FGrrcbEaS!XPf zvlt2%O0qf+94K8<{_PWPv1 zY64aw=EZN6RK#k!5`$p_^GnhK*^Vo6a;Hw=snxvPkYrRxHNslXR>HbOf4$V-GoBZg zq32&xi-Dfz6lur3i*X;%kIO)umF7-T%WyURKmzr%jrYB4RJMF=fFK%6Qc>rgjdD#2 zwqF_`RA0^uSq0YncX$TghvR2*Mfb-h+OR5VmqmL}aL+1&Dim-kQuuWv-`C#>{uA)t zs$VN34wHiac}KcG4%yf43V*gH89u&HGZW)FSc6kYthGh$hcaI80p+P%J3SZ2@^UVH zRV~q+Mk*(Bq(_Y7EL>VU7c1<^G{h6Uq`XPb(CNZGE73-taOqL}9c50m^V|Xe00960 z001EW-^p2I=8J`;QiNW8We};4o5Qdh~A4WqM3aoZBdHOy+Xtdv_g(@ZvU-%J9v*Jr-{9J0TzTZAP7*5#Pfqty|)IgM6^5Ve{IAEeDB2fKT3Sy{tLz5Kb81j+Kv4W68~N2@U7-W6%efnPVN@|4^kia zz2Qr*>RC}>k$ooTj4?DP#nf45YsCQ5GyIAKoVy!Mao5!Y`k%H8OP}L%U(?Mp{ms+K z&LA;~Wk7b(E{8>e&v(h0_$>w@=>ZGpxIFvH;0~;MvH)=~iEC)2kIwf;thzq0Ywf_y zrNXyS8>i$M&*@nprbc3s2X{MKViY0Y5x ztY)uXs^b8CloJDjPp03y2Hk@5GZ+=3XsUHxYT&eJXY>_67AJ|AWfGVaW+08Y76|04 zg4XvDk*E&=pJ$AFpd~t(i3`Oicfhj<-tiq=0%ec&%#DFOGb z(IT#j`EtW4tY$lD1{M@b5d252>_s~~g!ATxfw#_x1LW)Co zrlPq3xAHQ-|KpJ6bL^3IynU(r`gZF6n<@eRm^LmYbZn{Vy&3&`!WZfY>KJrW8op`I z^0|NTggrq93}BBQ8;8VO19?^-_E6oj8Ok6Azc$y$Lx-{Hp@o)6yn6O2mnAREXROk& zn5Hb))!PaPF^mTD#@Z=YdZ;xd8Ai6(#S@bJe(7HGow%zYf59Q!7uXE+Pu%w8GXA;k zq8aOx1mwz`bZmB(O!Lb697#y(9#8yBE#k3N6R$+tR#Qga-B6pvdwU}#`}|B^w+r%g z=tKr07Dwdf{+eD4dW!2I7aOv|^<`knnolgAWbRHxK#hMh8>$PP>875-(zXRpl$?TX zfO5~GSJYu*d;q&pE}Hp5?-74z<8_@Wd}LNcG|dxDi2Ddx|Bn31_>lgu|0eyR|1;_T zooxD${>hi<=10BZhm-_;O>3U#NxZl=^kL zvGm67=6S%qldYb185HT#Q0yc4S`a6@c4yv|)*Fmdw|?c~=a%?J6cUxLUbbG1!0Jq< z(7dY?U<>_)kY=`?WINqVxTDfnqHiRFOz5kDHi%447ChvceqX?GSf<+$9*6m6G2pNe z(iOND>Bi?c{;`Wm_7P|A8wT_^a=Pq4V!{|FUEib?Mnhev<<9cXmJU+3^2X36-kZCaPu4rSx1YS+?e2bF4Y6|8ZN(F&rXtJI22&S-GQa%;aCYoO`WB=7MtoX1DvgN41SuA5paZRzKxb$|V5%%#!aG0RioUdk-1)jH|Ma?{pq$lF8 zkKi@?Q(7SxG{v2$ny&msbSnaBZtTN_S;W<9;-0z5suV=vd9Dn2%mKY0)BQd`15%&H z{A3L)x(7trD23Gvyxut2q(|W)3W7bc5Rx62<2J*wDk6F101xtOn4HtF5>IK)g_{Vo z-ZgS96K%ON?$>-p&o`~zz#$#V_=P3wefF}BvXWar4i2!!Jl>edD%Sl_=Ep+RK0VM) z7VojP;L0*VSaQ3`)~pwt0Y=8_yB3fbr(zg@s?UpV1d_4@Z>c99tIr)f?IUW-ytyCV z&X}E|i<1Aawv+uWzz-AtM7@$@djsjm{?_KO4fprE4!;QVKX}#;yUqO4?p&g*<9BWW z4oh46c=vBB{5=Xv06mJL4<$t${~S8cpLG7V$`gjF4(PHz=#`h7SZLmcO#{4}DM_N) zALf+#Uv_2l!G|I6ugs#C;5doL&jLtJ8WMZ%e*8yu7%WRFyaBV5$7qlrC$sr@xOdJ2 zpI+WHT!AN#$CvHz`$B==fWxwTvolV|w;n?>@&nEs|IvIL@8jAWmNb%}&L|0gJtK)I z7l#fqzc{3rFAwD^C&QWU1l$fvC!|(=*rZZW zkxhT+rTXNh^UZ&9kLFCCn{u&zCMX247eH+gDB=dfsnK%;bYYD99A9swb-w@vL)wo{ zBd8sL<5%EyuUB&&EyyiXLqQdMuE#{@-NZ2AdhVs%L{5i%!*IT>?so?DkXGA4|w$eE{gzA@A_cXNfrT|uFpy0pj!N*T;L4$p7 z>cP-P{o8)jpDRY*ZZxBYSK!T6@Pn%0^CA4<2K(V_Q*EyKbk7%dzAyA?YV{S2snSa_Mzbq$o2im0RKpv|6Jt!aS!mz_WwtDvXsF@fS?Z7hJvYUbYYd? zxv*zZde%!=n6T90<6uhuemx75THuEH1goM9B5}q*k`{B){BS~E-hY( zXwI=oDetrUjMwtSOJ>g!jMjGz0=3cPE>@DBVj6fp6DI0;{NZ@)IrrO_`|fg| z>6XY>(rfV#rRgV|Mb91zjn13SZt zPTh}BdR?iJ`NLH6Oex@a=zPo(fqqL&q6mzPSb3}7Hd<4T*XENfFWwxXm(+V}qWPwW z{9!TdkE_IzugXiv+Z2O$_ayEeCe89b#fpfVvo=ISEd*)8EzMo5DZ;&CTEM z#d&$)k`Dm`{3>Dosel1~l`!80O#esG_9Y>gJu7^T-T}IK_0Nt^uZuH>U|^ep&K*#B zUzk8;V^<9M(|HoFviWdWfl1xcFUa)u@HC0?C2jA394a-4%Fbv*YS%W~3jGwC`g(FC zvAthynKh=(feMsfQrg4<6$BYZ9yGVo&!u?mTj0(^o&3~K>c9k!W}Fh&N9&S5lbDNv zb3Vy^+PW2e8mjcHB9h@LXDA4WEqaQxAYuyOdAd?XvWG;;JoCYQ-#hv|kII8~#zXbt z!6h7<13SYl#9Bq7fHG^jxD+~(Gc~Xn0W=H_j`lFB&=k%#u{1h-EK`Ntz=Ar*=F2Vm zd>6=|%HWq7Kpq~d5Jqt0X@7cBzb8O(9m|+x&zKruxM4}Udc$$V#p8epW!)XA`+RN) z#__iod+)Twd*RSD9*zQ z)0_m_*@dBlLNa)g8*q+pwwP>+-1PEIV{gcUQvB0A5B5W}B~%$wS7;z<#8 zXeSfta_xl-q#`-oPh!h%4GIywmpRT85HSpQZ)K&}Za+}G&f>;P126Fm-gHhWwg*!9 z7-9*V+U*|Mk7$G5;%ck(=}F`-KLsw$p=WGuF01$k)7lLpNQGrhbr{uRb}7!yUh4}x z5vGaNe2TeLurTSj!z-8f>;n#jJFSPMSoaW8Kml1G=r{F3cWk40igoKbZz8Gn^7 zD)vfIh8te>BQ4np@F>n#WqlC(IZseMj0VNA92|Z+4}MkDQq>ok@bWUjBZ=jm!c+a? zHe4R3%RaEJ4KtgT2apSSYtGy0W!HoJ%PPBusS;zH$q z7&yrKgc_0p&gJz0n`Uj35q@`a@FCPHLcD||Y4#U;Av(*wqBBYT@N7$T^Uksixj#Fn z&tJfAPD^5_N}_lCvk!dt_Aqc%j0F^RoR`E|@=z6k?+%bfV&0^(LNBm}hhdWF?xFR8 z>kkz98+a}p%C&nl0{A9!9MwO27Wh9X_U*5sA|poEAvo3fb^8soBu{UFr@`+~lEiE9 zdla$fzJQcD(D7&gPR@Cf_a_H|*1dU=0`E(B_KIo?ko<;)_a_g+yF%m8_Qp;SL`in) z5FozxI&a61V?%JP7mOkGDd~>}T7PTL;j$i+T z>2r>uxW@3%5*mb$(=1LTPTpE^4ZNe zy!z`_=1yZCxBLp}W^ZxRK+l3xuGet)|wv5?24dbw6-uAk29ga%n ziaz-siNoR$0kd_@wQCB1R~cQP<;>x|daC6?L5W?zy(pQSk)bxU4jEj}m|fPDrS&*2 zmlCAbtlu2gv6_uIr1BkFrE_84WM~VU5XBbKY;f0NIYf3s2i0S+w3fvXgDA9>=bjXT zjoqGTOFnu(N;P1@&djq@sZHxE3al`^Xy71coNbfxd9XS!_L%62hnfEvE_Gi!a|%Q8 zaKj#XO11b3umR025n)SvdVihWi-JinT*RC5Smtwl>EaDZAKgoY@@Hy6+l{p1I__vD zuJln2F#@PBV!e5Fq$l*#F6D`MOo5%mhLLbjyuMfkLOjj17|AeaV4Mxypch)REqn29 zsxm$TyXe1i$XkM{(_{W#+L~fA3x+84E1DrVG9Xb&p^>Oi;T&1HXXIvI6sF1L4!Kh}8nd&a)hBK>>~@T%Vr z?eC5Z_|wq-G_qgIjDY`8XS9zH2Ei!05^H#IaYv2)NV&o_(_A=heaBvJSl&9Slg<)NXffR>RdKY$~64K79h;tHCp^Vouz$%eD!!MQ9 z2e)PC0B4lKI&tSL+Wfk0_tGaGhfyrFwB;3~TxidAl94ELL4sQNm;}@jtkHmABr?+; zx*o{K2QiU4lh**BWSD5SknM5dV!6#`GwM<-d_dMXC<=uaJ|GP++>2e%)>v}@Pj1NtVk7&{vo9lxSWng`Z({{PJfyU_g!X1Y zwK{Im@oeMHm4qL`r2;bnN5lx#Zwz;T0!~GqJB8GqbLH9>Flw3JFzm)!wNuzG#9S}J zYb*&R;-uPWw`JUWaL>BPQVn+lI}D%~&~ms|IoX2mU%ElVd&2WPzhSTPh+V*2D+jC7 zPC<^XgRMNSmq<=)jpA0V(<9jdWRtyK?B|BwpRwge#4zKXVf*Y^DvB+r#M2%a(olr> zlU6_^@Ddas?R!%84mgQ^KLMt7Z&a1fE>mxBo69(%du*e1l#&%TUWg6tw`;YKhnx)N z9gkm|PnG=jM9%GUrT%4!k@Ug9^F1g`i@!|^qOf12g<#p74!lqFS8*XY@A!=`7oSkr zfv{*hMzJPox!ge4A~~tsCxW7n21f_pqfTm7!(a0@*I%w3g6o&G&AMLMkFEBB{d${j z4$HB1x8Re_bJ#P+w-FuRI0nA9tL0ZhqEDHXz<(?$k}2P+ymXr>tr=4eEP@lnmE`P$ z)YW!~vj_G-h_?{6u39BrHj{MeNHJ_$0azSrW5*t1cTsQbHPCMiex8!M!;p;kN<%Z}Fusea!v++LKf7tV=J(Ise9uDDCjxirL_@si1Oc9g4t z`Sv6_Lvi6a!V-HJ81|x1H=bF~6{2HhKM;L#7WtJpKxFRHxGzkwnd8TfOQ-KAy6Pucf25B2qy;KZ+)V85H?WtfN)P(_oc0BJQNL9beRM4Z{!mh6eoL}v zaznBn%)^sx+pm_t_#=ToC!^5O-rq64lUx@bQ#72rz6=&Z*18iJOmJn*obrYZG?5wj2hbK%nbUGn-G(EEbuRYHgT-S9< zrO`YTw~TyZ8;{WWJ>Z^3A&E4T1Y)GiJvu+anDvISEkHAaI*fo79I$IV+Yei_(e}^` z*Nor}RgDv{pI9q5?aB?$U!7@2wC|k=Ev?Sa9+{4Xt+OiX!W{*|rxQG>N9!^Htddf^ zq$VU(j~j#cTRhDdd-Lw7eHEK#Se_cG{u{aTdK*v=6C$k8ABM(1v_ps*uGyVuPyRT1;Ef0Bw*aw^}4unV7A8FpLd;FBgz{BcywE8>h z`Cj_SZK|CdGDzAr_M`N1)ogA9R6BSJCPdwfNadYhBDa{Tn&(CQMzg!RAK&`G*x(`A^{*tG{QjOMsg&cQPn|kmLN#^fKyxGquickum+&#{NiI{rt@XEJW6X2I1N&!gyAQX+a_%(hho!n+0&PadP>+m zY}z~~U%u?}lCZaLhItdEmjP0xTt-Cc;;*SDq(fnH%bK$m0_pbs8ZWAw^jt6RxUJ4Z zZ^R+%ab%Ki!+n8j=J+@xi@%|@#KAoFG`x<_V{fvqbvoX(PJ46yqp*bzn1hM?Tr@*nNe;S zdb^J%P|A1oenqY?hVsJ2)6UgQCl%;4_FeSjHbdoG!Ji?B6#{p$%!}GBtZ2Uqk8`&A zUsiGYZ&3<=?~i7f*Rxt86eY!m32#GBKiVn!ty#y=K>bTQr#JoM4`G(SNy8o0Ocwr& z{1v$cduMhZGH5L#)X4z@{m9|_Nglf&ZaUXCUDgL4E9pC2dxfc z2Mc`DFCx1+3rqP8!whaXYjdLjXU-CO4!I$9`m&toH6*ikr97-E2pG~K4cp_qqug<< z)RIpb_^dAea=lWde%|!0egKU>2bV{BV-fSx8z?m{HM`u&>Ce}@y@v;lPz_WcCmXI;qsz`fOzl9?t7 z+XrC(@_-9>U?W&%m0VS*S5dD0=VWf+HwS2bZ=S33}3J zo$~DoJ`b^a*x#f9)?)G;0-PyTuyi}QU+xni?AZi~8v+0T0RR6003iS0cu0=uRP~BW z<(`=+;TYTxkX7Z8p${vE2V?b8`KNm8sV#8im;LZ5d1JN;sK^V0-RSi;3$S!j@<%S- zPgoA}Jd>+dL@Ku?Qkf6|{V5lv)4sb@8yiN~PLRtwt_UdJIAUEKKCFgRr<1Hz8~LpK zl?%`53!@;ePH)wef-EZUqARsGdI_vMyrlAz!z^hAP?gb$kjHI`(UXo$(Fu-A*nMIo zGBkL_yY-^8dUVeQ?nDk5bJmbGx|67m(%PYTPC$F_1Q)Vp*KW?Qa>ceNk`&00{*9XW z=)I0?e^C?i^-vRg@PJxJf&Qc>n*ZOci62eKRGa@$6Nu};u4T5(mYj?UumpY!#k5FT z=fhEYv+G6MDNMEVx6fhw#{K^7+F|o=Ud7PgrVjkCbN@DV;D4R_x2XgF>)gLh9eB_E zA22?x+2GoPq#saRKU_00+^ZU1U4(5SHF-Mn^&CnN3;@?iwXN zShuCKOL@MtWvZn>FX7wc@kFb(mFUsOOH14t85yp5y|-JfnK`KLTn&#xW6t+l*u8QJ z>+PaH)?zju62OktUC*!!&21^uV9z>@Un>arRWxbEx!GX>uVMP^m8)H(wZY!e+lZ-% z+^L>LD&q$9P7!}|#pZFnflQQ^kK-<;gEF4b*DJajd==uxp}J& z;LsiGH{GFBRR1aA{H;2EK$^w*krKbC!ngZ?_l@*_a2T6wt)DtuXv1uV6u9?0?}l$k zN7NXhkckRFP@HXuS28bNbp_83gx8%Lw#o0+5l0@co$q{$A;hkqVU&!;A+FA%c}m5X(zoXc zIQg-6vl-^1yb@=Y9xG1Den*JW&13SUc*s!QmCV!ic*YeWiV*pXxSIwRl&@$DEelW{ zYRT%LEO*FV+9nZMo%G>7GRJ@)PKeWBY7l-$S@)INIvOXsd(l4r9mPF2zdfk9_unF4 zzg7?(qK@kTm2tjFz|3&eLp1W!APTzC4cUHkq?V8_` zfB&HC+cow}=8^W(HS>3Mq=!EE5wJUO07e@d%?2MlfyeP_k>WroZ{`}=ENL2eXEbZ9 zy4~1h{bF`~1qHt#|KR(u52TNtUx#MsR7*PW&UbHC!$tx>1#fcSFBKCXF}Pzbs_=6= zXZDYEr0^GjKz(idwudejxv9XiIodZ)ecz=Oxt^~G8xjPMB&aLi%_#<6ozFvxAjx_^ z6G<;wRpYEYk5B24<5hmiuce^C_jivrU0h-Z%1q`@n`V2z|F3rbPi!@3%tl7%Gyo{h4IYwRZ9fpw zmuU8V{|EOGComo(Sd<`u+}kqvfHf3w2=ML;EaA9gmu0!RR^LZ;`iTBgzum@6@-@#m zHx50B)1vU>7=JjlIJ)}H^cIi$>Pq9e#op;R?j66RAq9eX%@3GjQ=rN&pLC8y^A-IG zB+>h4nE`wk8gFeVs=ryl0*<{ux5)#jLlHI?DJn*)yvq<#>uLlWx0P6ROmZ(=r#YPop0rHeER7M zbrid$@tLUAyiRRDhk=YWE{#04ghQ@t(crU1l@|X5trN^nU>eM0u-ToFMH<>i{A<@= zSb0xd3a17nd){BbBzTb&viW0Tf|)ImWZ$l!_OH0#x%ER)q5n-$k^iTP>KEGf?|q?q z;PcHtbIpFu<*2ty#C3wfZxsQpG*t*-MoG`t>Ya1h1Qb# z)>xM{J|Kzo6_S*Ray2?wd3ozyM8%WNOZvsWw8eDb{c_4OJvWrPpK^D8z<^qUk{$6m zqgyA&!E?(ZWn|LtU6@84cI^Gz0(ohB+J)%a@>0(j*ZXRL$3c4dDFKauA;V4bcp>_( z1R#-}AW`8k+Y>?8$NTkii??%s^4c7ABx9XR#8j__af0IcW|g`yxIjh?r$<^n1Y0>> zAuQ1kGja^8aeE+mv+r!*THoRz&Aj^qd9DWMU+B7(#Knq=1rho&osTCWS! z`*_;j4SVB_VtL9}@A&=DvXeUH;}u+=@+!gX!^e_K!#uf%R{%R)7()hG8{OOBlZM7X zN>a4feR8=r0W=#YqBV`WIV3&%P6u_~egbD%xcsLak9;}g?4hiVH^NfTH)quC-MN{y za`iziMTzylFbjOVZs4cQamd-9BzyO<2flC={Ok^6J2twH@_7O5B)<7LY&<}R9qx~T z{{y`OXMA>2ar74jMv2F9{!&288Ahct0xhCH@5KM4bCmoG;<9MwI0pfD|5>A9A8Nu7 zes>P&_zOm&IKX9TOXVqn+1`rDpz|Pky;~8h9JlDp&oQ7kMEj1=MD@cG1b)?_??lt& z4~u!23e&F~ZNO)ArL)sg-)qigGV`3BCa5i-z&$kpVL+b0hUe<)%ms94K1A(&PqY!t zc8SrhjtazzpxhN7t{})k71&2Cn1gLH$Zrbm1tqxLG@;&Xu)e}=Ur`e-C#}1Caw-P_ zS@Fr8C1!l~I)8f#WgFAQVLq1xZq371(`qW~GSMskLq;HchR_Nb%*>b%w6iOo z0JuxjnbYj?qbyu9YjAW=heOGQkqfxyw0vu^V4Or#Uf^b9ug7K2*+h6WUi{{FPj5BriaRAVYDZQ8s1(>7oYc_$2U*az#n{pA{PT>S0g z{N1$y{L?{_K`NO0IPs+kDq+K2gy9)@kF5j>cgI%=pWHAB+WZPf)kJdh(EU=KOxp@vVgp&Gaw0E{`q{rg~Yp&;+tsfol`9d#T>WmA#{e~ zcx{FB5gexXZzeYI!OALpEYL?1_7yb``%29Nw3*&XOULW&j@SD<7OnrFR~LBv^HdJ| zOQYT&j6X*3LGzS{#{oYU=}oUOyo+9rDap1=>rP|Rc4HJ0|3MBiym>y}8|m#)`a!et zYb}rPYc0=lP1KN}9h%_X@irAMUq1NhT^k5(A45goqxi}W^4ks|0gXU#$2bXUkk+C+RUV;2%?!MLwVy{$@6}to$BS??T1maB7bX{<_Tq#!~PXT<FT?*enSE-I=_ot~$cr=MP zkss2jY>_z(Pv+AP7#&bTR1nBEVZ&ld3##{SW;2SU(u(cY=dCz8P=(kfb&WgIvp>Aha@YI7vxpxVfC@#L%?bcTP7 zW2Dw340SUCWJ}RBX4}X%Pr3GFm&MsZM@t`GQdOib&c?{&eCv+0kr75Qb&t}Y%s?$5 zRg~|VTLSw0+*a#kL#f$(k2r>xB@YjLzkKJ8Vzkv@4of+sDVn7YMEWfn34F0Xg#Q?h z{2q-|L%pwHAvhayr(z{WStC%n8-m9{tg^wkaO9gOYf*4&=$TBAf1$X|#P^P*_iu$o zK=zgB(Bo3pu)eU*a@6OcJMwnZO*U(s^Z3HoZXb*rJcdtF3F#pd=Pv3-_>$VejtT zeGMG$wjWs9bG#$CK+{~1_uD!FkMK<2tIM$GjD3Pma^2nJ(z7ybn`=?#M)=v??g=)l zVP|7c!V(8|VN4VAncLG&uMr@bq}KXvdQL7~w=%IP<=Q9>wP6cqw%rU_v0`5o^w)C& zMS6~-p3`7u!;HR1 z^ay_aLuscg?Xqv(`_*~_*UG|3K9CS+N5qc3+qq|o5;M2`qKJB{l9$IVjPa93KBw$F z1&wwojU&`P9@rx!8Sn7`ZXm&#cXO1`7qhndC3`-lEqt(2`0t9eALABt@lQqC@;AO; zIq+!?aYQojgHOT5i^%B**3d&s1>PKPI ztT#RdYZWZgKp`Q%s9++G0Yz9@u#vq?2z((B-26JPz#8Yggn+#UmuS9)F2bNluP3O0 ziip{J?j3QwY8v~nMhfUzW((wfeWP@~ z(a)uKrB5>1Sl-dZU$w@FjQ*7-Kokb0|~~2$mN{oog+{SQhN30FrsCQ=dM+oVV>p zCeez{F@XeR+jxt@3I18M*%-+j)#sA+2?Ab`r*p*#7F^yr7sF!J#UR4&DiP%3Tkl@a z@BHpoX3??Rg}=zjX$l97nykazsz;%gZ#$Ah6Y>luvs4dg{XehipYt_!!=eXaz zX|{Ct1}`U9k`&j@GI=-BJA$R zGo$Q-Sp-OQ>;NaoSE0gxVGXAPF*iW=s~1?*7L}3I13k&8T*~VMPdyazVcrOCplP=2 zorIYj+v}d%jup(y6jhv=Q$SBVt=)=f46EL$lSx~_MR1{T@h|@>P_u7!xFz|gK>hs9 zb5{dDL}7C^de7>-c@ak*T^&hg?IHObBCo|q>N?tfM7~XBsn5vQ0Y81{`#7J-ivKOL zUIDEX@dH}#M}Yq3&bYsa48I&Jf4}t4l>`6RrGI_~_+OX)Yg6p!iRqu4VyHTn;Mu)4 zwCGGM%~$9J*N98TUd0G{1`BbQgA}-^w;Y*FFDxdrx{p=Ip1F%eJY8_FrIQKEvIiw3 zk;w}y4zRkk)<^Bn6Pkjt|EhXl(sk>+g~A2B_^?T@01tf7#>NF|-;5r8BeRtwMq`W9F;iP-Il_XCK3Mhn_>}s3@ zQ^Drvt4o|J_})g>hn*J-hI=#BwRdpaQG;)UOKpLzqTa0+g^1TB#?LH}40G{*N%#gxwUW23|*2(gpp+!u$!f zlWJSC?D3eMm%B;C3huaWhm&a)=ZQMiApu7|&Fwmc{;CI*c`>6kW*)iZZx?^;qjnZ;` zT~nb*Yj=iKoZX^EaaPkizD7^>xkfLQDnB#70y=fOX-kIT#eEGM`Xm-zC$Tn4Lx&W&y(P2K^mIM>Y^TY59xH5=YOq%tXGQEF z;R(%zX+F3padulI=ko5L7Md{oBpW!y08#;+C*6yp(nh!P731TOOV2UTT0f%V>BKWG zNQ6#SP*9wx&q-JlSEaZqYTL6uc_twD1>W^DYv^cwnV}e`uD2`I-#u7$a!2miygKiS z-E^Zg#8g_zAdlRKx1FTVVXjsH!oF}zPn&jOkJh6_`+kuZG$ccR+1q%A?oM!F`Jf;0 zT&&GbLC>*gX%!X+b$G5+6`&T-KZE&bx^yTzPJ{+syvr9_O;+_x%G&wXM+xZ9CH04zvt(?rR zx1DR)Eh#`6K+f6>ZQfc#j)Ho%JM|}WJYR-a7$ele)NnBedH(35B`j6!6*JaoqQtDm zv}PEq$O2!r)ZbF->^D-M`DO6`XTgyG`zc`pcn(vDS6@B&x#p2ZP}S!t;O>t{Ky2#u zllHF1DnG7@O!ZHuxJrMqYs)tw<)pM9+v4d%wCfu&W%paH^bGi$*V3Di!pxZ*P;Fk= zzm8e`7atZy+Wn!NCerph(YD`jFt2{)EyCJy&D1+hH^+Cz^|S2Q7b?itRRdrC<B=t|`b2$Qjkso! zx=JtaGo(GfFsbW2WT@wtK-!7i>*O=o`myQgJzbxE2tvLk$a27I>hYs6&CqY(wd%Vb z{k!z{t&G8Rs_(?d7k}zE^550rpC4jyz&ACxZ#U$-Vy*?{8o@P=xfy2 z@0FW?$^29K=FhTge6#rgdG%E7?mluGCz*K;?x@r3o4?8A=ooNnQTQ5$xW^<1E*;| z=iX4G=-j)s1IcP)JXj24s?P3JpQD{Sb3<_%UqY37;DK_VMCr9B)7Oqvd}WFF76|^Z z`!)+dH5vxmW9z!ydgg(bSm19`66tJN`5T5j5Uz(%Nyo6lr_prOhG1yf?W8M%P&^7S z6%-m*0M0T+jThVf(Zwz1(#3J*$z8TNUfocS;r!P1CntM?2sbZJ<9SmVpL+(i(8Sg7 z@Mb_c*K2<4dn~$1e(KyF@Z;8#NS(2bQgE(61=avUhG(8SK-(vDFb0Io`$j-42hLzxyEkw!-zjB)qAnxN0W1tEIZDAH*c} z*JCSi|FtB{M=zD7=1&VT=@c(<^QHyBb$Eo=ul_gh2m$=D!dv{wB3S&UXq3Gbjo#C_ z(zBj#yZUUMX9A@+2X5p8kY2egw+Lz9@B#n;0RR6003iS0Q-~CI?Q#y>)Z`+hqeog0 zE{Tox+In$yKuqp|#FC;6&8gB~Eqq&}io8PC^(t6+d+Q)e7F{2O&JFr%ZVmv|?`TzU+!xHj>vNIt?wSUi76-7E=Wb+}%L}MS z?B1N&@ricvGFg3WDRn}g>*)*-JavhIL{8ER;82(m&phsUdu(Nxa*CkH-)7tpWZ(cQ6MZhY zltE|9a99YNnLn8)RQ z(S%u|Z=^=u=0tPjuE8mJrD54~sq;<6cc$xH!q)5A6wkAJErB3P@DSaU!&epXZX#AAO_YWdc=jo=Z1;J8ggggG_d5;c-LPOK zxdvfSA#{>iy)Q~H(a#&05^9SjvQatBm)?d$PXN{Y>>i;_?UyMdfZU>NC_f{<3GoKm zfs^}$9-X7`RgKX&#-=?ksW@NC^q1PB9MujIOMr*|RPV(YTMa6*daokyOOb>lzxd5?pabu2+U(%@7pA%0HeKpk={A9VPkYah|HvPX9C) zjrROPCziQ2 zH)EvUBjkg4^OH56{>fMTb$9>S-}D!O=D+Si_C=rh^(Ke@Sp_EhAOJHT1mGiUI4RBA zQ@cO!mmH)QTg7ijCShf9D3U;f(33tEs_Ii-yApJa|doCT7;ZS=ylvlpGqkG0*}J6_u=&NdJEqr z_&Mp5p5^1EyP`b6?elt|_({#TliMVUt-bafbWI+8HI^X7Fx`1;+};tfV#0GQO{^cE zWHX_+4T;0(2~=_5E=379G|@X-csw198M(!S{2Rj#Z&g)xpSDp^`Vy+K$ox}@i zhED({sawLRSrt{4+*qBnDX18oS+_TLv|7wSB(Jf(v5bRt!9`!oyA#73wLquPkoS@S z6x53DE)jIeCGkYNdmK*zc)f!{rQ&%IAl`|4jHsF{+Wow>rvnekEgUmtkv+w_ksKf_ z%@BFWxGK0MttoAJkyp;571zXH-MJ|;sDlQO#VgGPBxP9i z(&*urNZ)RM8FA-t3f%si@gMJp#ClHC-U{$6Wzboil6YK6&lZ9kctGTkz0i`cjI%}8%Be6h zRL2B+qOhlAuc8pBFnLMIYPY!dH>ux2(MB@MJop<3lylp$VzNYETakr75Y%5Sj~na=`2f zsokP0f+fpqiWMEuxJfWZOno!(D806YqOiS&^c7|gIcc+X27>jx^&*b#A>_bG{c4_R z#7f#1-p8w^^aJt|_%>8ErA_wLoV%Z5v;v-6$=F8$e-!TGgnLrFQ5 z;x^3)>2P?&@qj_iU#6xF5 zr3bia_7hv*@msy3BFnCEMv z;lL2?&>6gNsrEEOJU}69WHS(0^@T0jyN@sz4=S?zcurV&JR*on=bG<1P~AiY>Q69q zEsXUvK@f(Stl&x(Ild`Efb)_260nFJm{ZmJ&PX6z4I+I9G3YDEpjr*}{<;`ukUE>RaitPT4 zZ20DmU0KS>eseDH<>WtV@jSEh1qGGqa?`fx2-~#+p-~fh>a4%#<>WaBmko~F#2#+x zu40y~R9cPD5m&uDTvN&HRP&A$!GYdCb+B_@Z8LCF-e#Ve0_j>^>RW(G#hNW9vddzN zy3nP-x`Y$Jx+btRLoa-5gj#$iL`j~fwa_eyZ1K zL(+@#3bF7CHv037aZ`PpmPFDe1R=P8sNcr4Ej>OHQnQ-7rKI{j(` zv{<2*ZR{&5uaUSHL}Mv(3uYa!oR#&G{kt$ae1y>-q^t+SE}7lYj6PiR*cl|p7X;(? z8CU-QD~wXB@FO0@U*pk_d4bQ=1^851{&4&lM_D1KC1UQ-y2~i@XjXR!X-b%(@r1R#nkt?^l9%+CvSe5c`tywat1;y;^T2VHR7Nw!Y z`RY@Y$VvN%g&6^*yE(n|S#kU^;z!hL`6o#LZGN`Xj`3(wfK~x9oEYLH)|3m$GARc#-8Zyv=(@S-gvsd1>*wlp=$YbDmYt{ zr~|YS%V07m#p;QeR;Q;5-yjUgVuvX044U-iX&6NjY0np}q3D>0n@M#y`dm&%2`7^a zmX&&2q|Z@HL|u<3;RgIJ8Tf;w{7*_a6p24HJJbPFnVO4yFRrhJJ&-ebvaKJ9z>hrO z`^mpM_s^6lb&j<2yB8|T-~@9mM;hbZOoz;b6Soo%Ozc72H~_~MFwL3oA)dz3D*bHm{Ksci1& z`#BA#YnXaX=$ss!E>rP{ZXIfL;Bl5XI1x>W;AxUYi3jd&ZB<3!9UwsL*>t&RKJL+B zGTgG;?wm)Re%FxO0JAJm9xBATT+S91qRL!y_Ng8L&)_`xVN40Tj<+X0bl|-3y4fLO zOV4ILVjVvg3t7!>RNFgCT{ok|;=Myp@ns4h74VjwAQ*&X2$El52Jh4R&`_K)M1}b3 zvXhIQz89|$o}H5`lcE3 zCS`uo3|a1L6s%`&|6(TgQXk)^Qa?`m#!C1$TK0o8MZMJGr+e`J`3EBXX6FXzw)aJE z|7Tl{|LDr0hAQsf8vrB?0yj>R+J`CbanKf>Y9sVt@_4svR&SpNxEp!0>ni5;Qj)DC z8LyLT+A#+cl}rb?Yt!i_>+;T>>THSS&Q^`vjo1&!`KnyJocg(OFSjbc=XbBZf}rY- z$X*!O8rF=&slbcLX**pM=ULflD?GK3)S|2+m-2~O{Di9dtc{nb(*3?2t|yA;pWH+| z%`?o&%@HI3vBGQ5OX!EqG>N@QXkN=UY0Y?jimdGgHtH#$^PmcZ`{TGFrYrNW6Wm?w zcuM>mhXVOdJM_)cC+2uj79PKOMM35KMM4hfp~To_e9Apr3`}D(3*yJMXVOo@N^LfIz0RVQ$A0^p>Gi)4f&sss1XDP0MJg6lNP&tCPs*PnHIt>! zEbR9ogjif3o=OK4@E=e9qpb%OU9-SNwIl-CeG~o66YWh1MJvVRCh3<~w#60ourF8n zf(}0CI5#cr6Nq!*cB)m?nz1U$Sw%eWK%x>M25Wc}hqdTGXry+8rqC<$*)_X%jy?rAt!Szg$pxPzHepNiG zkd()Ib$Jz}pK_mvsndynz`FH+Z03c~dBkPq0n!jLLR5KS=+FH^9;H{duvxc5&QvNq_wR(5x+aDczoe~|=fbJeLYaQ8{?(sg= zI`cPClMjDc;Qp)CPc6PU^IID94ou9qZu}Yw_Wp~L>&HwA@IhJJZh^SN&0uK zU-a$ep_$*4^l!%ywLDOWY2i*u{f#MlwaTB{5FY_qpvU;vjzaZ~*$=#_{gxngp~G+Q zQJMcKvT3geP*0QrvaZ1h`FX0P6>^|?Cn|k|VH8XDF3k)L9$!mz(p*noccwB&3cf@c zW9WEL=zyKe3<**Lsm-%zoFz_#hfwKvYCvsmv_);Z7Z?7CTBYi8v!Z((0xBm?#~{y@ z9-9JG5fwJ>?AsZ#5R-h-;j~Pwn$X0ml|(Zck5xDv0h$vTEY)=ysFJ@@#B!?dbEq+I zRX@%w@Vc9FOYzf~+UBf$Sq;v`&CE zGuSB^AtsCb+WJvJE?I^y%pbWm$GoRCjtEC(oct-=4ty%N)8#MPiKsfEm+>Z3dxD0y zYHJ&;9G0glR(}%j;I1kgea^nV2`9hfBz{-?{PA$j-w1vu%`h3V{9x?w;x}61A44M3 z+A1jObgQ7G4gr)#Iw~T=B+Sv(ZDH@^Rn%`)5yZR2|?W?#^FM?2NB9ANEE3Y%lb}c_&Fz*mh&4vwI?I2qY|~X}x3b2-`?_S`JcF zVP2>du!XafHfO4!v4vM2tR!b!xZVPNTi4~SzHt(nh+g`KR-EaFw$f+Afgo5^*C9t` zhXyKX(opxfCPL9%HSg=RsL3bFxo##d?RbT&_I@?}hqz%P-eJ6HMINk&-53W5r#S>r z6JSvey7g~DqVW!irTmxhx(u$F7L*dvODfx3l_jTw-$KndY3Z*5pZrtWTfF?15b7FLLNCz^yoE!H+L3%Ok;?=wE^dfB zLz3@8qLy=Gx0@__NvC+8Fj~!wKW9m~7DZ~vw}jQ6QdwfIk`uA0ksgC>igYvRI!C{Co>cHp=??(6MP?4IY#=*O?^!uv|0QL5VXI+MmXMh3xAO8 z1=92Aalg7}(g_;u6wlMMo}s}DBOBK;w3s@jX9*^c#^;1#17-*3V z4y{!E*;vyU^@w+W$eBNyZNRT$dq0o<8|@hAgdzxM1mu-UaG@7%XSr8BJ_8o;n}}6j zi!J0=I_h;|maiUq8$kB8lghd_S#8iUM%KQri6Cp9Nua3aET*9wC(2PwKjXB^0yG*; zgHSX5X6WZ=zoda12D1y|3!0e|f>LY`M_jX9W_JLnMbN3|=x_Mr>{carrE%|SUlOVw zR`z~<4MBVCCV>*pjZS)@3=Vapo;%;U5JmU$cR;_4!!9+eb}H`}>?>q+xwC?}<(F{P zmC1}6m?aHgY-*{U;9`K97>V36WCO|JX%z<~_R2r|jB!d@z+(786Dz~`6m>@Q(vwDK z5le}iLnHOC3TU3T(s52_cYE1r*uO&W3EaYq?d!WpwuuvDy%w*_agRr?%+gQ}J(=hb zMl-F)znS%9-k4?ii^##+XP=pZctXn&q2Bcc&qjXVoe6)J8~+eFJ;I0k58>kl`~~<% z^S!(yc+roOZGMd@pCRR8X}q<43n^Opt(pjYbYIFhC6mK7Gyi7V_RBGqAOBWP{H$Gm zxATerbFBT!PkE`L&cE$`cve4hY2a%B{vLlnF5!FpMgGaV4ft9{oJ|x~)W$*uN3LzS zJc~LSHv#VWe56l^aql3U&2Fc=b2S!2Z6@bF18?IPxZFk7r&C|NzIrOtOs&LEtM#;o z2Q5X8El@A;o->oSSEl>;qAg3U*N=`@qp8JlL@j+ag;_{(Z8p(SY`9y2##Pp~B%t}Su^ zV)nkN<=W`bvy~`CN^>|YIMD=x(!Qjo+bK<;N8R04i;#=&w)rHqxLG`D`=Qt-h^i>? ze@t!vo(Bup&oq{Me5A27FVI6^z{^{JD*kws^$K{~CV!N6uHX0uBBh5aU#<4)$sb73 zvEBfYrc7E=x#$giY0lW!gkzVO4Rq5L{J@OFdy?hJ=3r;jIb0)n^2pqqUvg8qbM z8CSfTdCsz+>+Gu57duZRBKXXR>~H?4e-$+4yH`%ZhFmZn-<9KHkBtMg5uEpiR%#w+ zDqBO1B<~4PFN9SA4^fw}n0pS#+kC6lwYUp#jNtmV9MLhjRPJlepi~}nbx8Y^PHE;m z@xvvrUkrUu?hue;rwx_NTF1I1$nR1uS>$OZL``xZnPyCCR!}y(XNxVFFf3ihrh-y* zxCgB%gW018TJ9Clz1xX0%=;PHU19_}C+b!}L$-Rp7M1IaNE*fz1BPf~d)FJug*&1s z7nRjI9T>()A-8$eR(D+ZsKmThQ9y5ez{%Z#-77#d#t3&0OMMpL+7phW^aK()5_>1N2j7BQzq?_-yI;Wna>IUizkvVc zhW+k-0sqSl``!Hl{&d6sTLmxRz;vC~5^QB@>iTLtMlA(LnC|>@tM{s+1ysEaf@O9~ zpC}BQAkwkrO?-DMQlf8@6p&!C#>Oc|w1Tzhm@Ec|xv$1;(%jVu;%a(fv%4{oCD``? zyuuINJT;OmzCgG3xi|-Ov?W(wc&&chqAK2lXAq`LHq!HbDdx>4$Q>G9RCLBsZFhvJL8BKP=JY zfPy%Fz&;2&5IGHn>t4S09d_9ehi+1-xV~O| zqm300uQJ>Ld$&@|T|}UrSf7teFwiF1HPro+2LIS;`e&_d)7J>?MyII1;}-+q`!iA) z&>)$;D6rp49iQ<1p|bSqQGZhOdPjcXx2-He%IYDNP%Z1+;>Np#yen=<6k6m$?KJ6O ziR8|fip$yq9HWf=P_1M?d2o3o0e;m{3L^QHK*ZWvKTQEp0%tNwu8Aw z3K??BVSrSlOBX!Ppvx2Z)OkXzoz_e^-<#TV&!`e8n5A^nxGG`vd=oieLm_F;Km+M^ zi1{7JR;0e>@XU1*m|sPTCydEAuinB98i%%u{g`7bWGs>Hx*i$|>E3@HY% zp+1>tI3Z?Ofs35VkZY{;Q#=4=d&KkNU!afhJ1e?yy^d z>+h;XD)*OPG4M?vSrdP0rGFzX!yj_v2ULiDu^9VCpMFog17Sf6A@ZSZLVs9P?&4p( zC{~13HrrKJg})Ey|9q^Z`Ck(T)?j~brhR8UeWrmS|9vW--;WrsemZLtt^dtXLbb)3Cg_C2EUQnKBU1Gt?=%4UD^@l4N_! z!3a2q>P5aRJEh+sXN2hK(Pc}Fz>TAuv&=Xn0u@r5=;e(rIO>2M6j;H&xLffVEW@4y zl7_kj)11oSo}d{Ag%w&`VyH|qH0d16Z*{LClQ^VuIWK)!GyU_{#TVWhV*9m8F`zcR zTOS)Ia%scF^oiW;0ssI2|Nj60AphUwmn}=6VYaQC9LphXLAGCkvFKD`ZsQhO0r}+Y z#HE=ro&c3i9`bA?JgX&qetfGv!`p61)pCucCz#Wuc^%vQfvl^_psP}Hf;%T|T#6<7 zJRuvPj=RT`gEn38rj1R~T|lzlu`W(xutOwo*sN1$3Bo;GHA{V4T3$pa2ki*Wi{(si z0DrA+U1G6pTim1~XD(Evcm?(F_xcL<6}wXpENQ|;6mM|JbxzrF6eQwNHl4+%dM|+B zij!q>xuA}Fa)XynYz8&-ol_$aKDcP$nV=W%TU~`-R5D@U2ci^4LSf%-_*T7CAQMS6 zL6|_8K;%+o2|IK*`-*tj?OI%W3AI#+^KfO)H3QclNU0O^Tqi`h$DzJh%^? zMx~_2FOG2xrF%c-uK@*>>LZWY16Mzu`D%{7z5m~B72bKz@AbnzrmmRe3}Co^xda4- z=4pe+rA^w#nn4D!+Zdmmz%+J(<$lYZba`zFo3V&771x!)!CRf}(S8Fg?|>*QKVw!0 zUKz4;LXY%CZose`hZnL?w&;-~$-Wn638`d5K_AbND!!_{aMU2cfg7ws>t>jCJ$2Q* z^J_R_)a^d<=LSR7_(FNNRIQS;Rfs3Sl+KJDv?*gDy$LJG$S^>-_5?Q;g0V$9sAJO$ zSKnJ~Dm9aV7-#vSn^#>t*?pKmOMGsw^LbX%NsM19ID^{)T<=zIr4*h^i5*_CaNQOz zzS6i9QnExssXK}IezK3fY)Qv$O?_Dy4;#+>L>X~EKi)67cmNuNPhs>Rk^8z8{5=YjY=x-RAFdG z=r^<44b0BU7#n5KuP z?TX(?jCamTUoORM85Ve++1U#Y(JthsdIpGnY!u{6kr%P2;&ZSvTd`g2Q ze#ZP%`Zv4(FMfQY`C2RmHVEZ3{@}68*of2KWgc{BAY>fB=B6!%?sM zRY*w^FH8(QG+Gh;YPU-^i`zhU2{K=_2Hslp6 zzu2=PG%Pt6c%anwCDXZXZ*hn+6k)j*rjg>FJD(@eDL5h=0M8^Ip(ZpS)Fp(DoZ6m( zo%7Y$Ao_TJ&ODP@AU;(JR)GX6StxX57;0%1C;f6Zi-ZT-kg{u53A_g^m=4Vhog|z^ zEwK2qE1om%2111TwJhv@JDvfWHLKUBO8V?vC*ihx%7_HKOx%Ob0Bt@`{0T@Tl~cNn3C*B;v3w<90n2Q|NqcnI zX1n)CNDF6^Nt+PQdn({&BR{))>0i$kHi{YqL>Ga*ow7d5E_p+gYR|fCPS5PPpTSPD zJId@OO2{}QYEO;c40el$1?J(rf2}xXl>qfgXCr>6+Ej`;CJT&pC|tZ z1i=0$1OR+Uu>1=I08qmHnk7_wDo%GyvR16?=oF?#7bXiYXs$t1d90vIaE);1iZ`xT z(i?2r5wF8_G4c*@Bq6GF4(`ooywH8^NrWe$BwsnLpAHiijog*phFgi*$3C`Y`(ws# zM(yORbjyd41YXSG!!L3p7F>TC5^uNOMlovemlMLqj{^q0Ok}#XeR|D1p>nHzekzgLRBYW~sR7Y1Xx7@OXI=}u zDfqqj0dY*YS)a87n?i))W;@~#q{DFpc}m8*qs6+(&!D;#AL47u;PbudabWWV>U=4;_f9 zsfV(Wg=Eb>l624*=h=Bh{C1Z$ap%pOCQd;KGP8FQgC$NLu0F3X9;DA}=Sds{+|=*4u_u4sF>LQv|$pq(+&A9U7gG8$BQAl51DO5IKx~kSG^LiiK zSTZ7dnk<4KCq|s=3Ax$_#-Z?i>TR{{gj(eq#P><+~{BZR&2} znpp=bpZ&d6r+X{^&0|RhxD^(Bhy0{K{Hk8ezSWDr{Qcut!SuF%`qXv-{wVkT4{f^7 zE*_ykgU(}+zm zIUEeR_TCas(YpNDgU;!!Bn@bION-`b?>bElbb(hQz*u8t^$x{BRRo$F>4DwGO?$Ac z6F8oh$AfO^m-hJHraOu2gZ;xy6oq}4X8kfi^(%Kv(T=CVkL&_s?pni##xf0v-%2Vj z{)eh3->vDk$J4IgNzd1NBLEGe=r1m(p;tk8-kv9+?Eq##nZHnWeZat(N$#PVh6KZoA|I9Ol{!p1D0v2*(BE*z(T^Z-K(dWJy?PL zJXrEpU7-wOcujNEy|7xRIT7;fz@yBAMUgRG8b|hHBCy5!ECWw@In6@hZDr;+QN6Wo zsTt>Oxd!yk73gKHuIJ1b0=|B}Ca5_@9%UF(y+v^6TNl0rtm6^uF0FBUNGmuquSer` zeK+ZZNn2vBr${iyYhqZJdkM=>+HY-sg@;0i0#B1)PYa;TGj-wQtbW8v7@?|h*7-6R zjk9u3oY~3JTXq+7I5^wYzv_31@2I!_ifr3CzoLP#GDEx(-op%Ugp)wHuYZuHDl5C{ zcK7RAE0;1U1Q9`S&OUahz;F6^{%qT@5Om=BT?B8(OB(&4zSzGw-dL&IgDN|7z|M%2 z$B15iwp@R6pVm9E(GO91+Pme&u3Yi#^|dM3AAVTi%@Nyt4)cpt`%>xor9Kt;wLaCG z0D0%2`;q&)1IK^2CcyVa`L}BVd|#A*yC%T*MfoRd@->tN{7v<1->TF(V;ZZGlKYCm zx#LO#OELHA77^wQplx&)OJ(! zDI0CzC`#M<4xDbB7de*PLd^O6Tn)a)<(K`6k@NFn*}eG0isfXSJ3`5e{E9voIaVfX zzHTt1p3qB*VNb@7F$k{`?@yp9$EKFQRO8lO%p zxHFb3Dgg3BM_}&7S+r@ZHQEJfj~RxSkb#3IAU>Q9S(8W2!Aqe7)+{a;JMoWDR!M9Y z_@6>izvUwTg(LRtfUXKWFK00s!TFwdk71PA6BP5-?;6y96tpHfhZ|=_AI5b$IjIFu z4#td?+upCDg0IH`E}V(8Q;{n>xTV+L;=Q3jSMT028!OKckXO&0xBL~meuu8Wk6x#5p*ZV{3c%6t zD&V^Y*w^o`g<=0<0r&L-{>uV>L=^x33;5+J{QnkkUq9gM0{#o~vQgN!?9FW9VRm{fUot~ zUJnG6_GeHH{hGJE=$cW1=^_Q{E<_ zjq6Q4afEKhtPr>(7pcLD5CRAzLu^2ySv@ayd}62Tjjt|`OLVUz4@)%`Ae4jlN;Djk z!PB5ONBsE&Rpp!&haM>oD+ry|w)*pyn>y+smE7XL>&}Re&l@Z0g#DXrhB;k=(gbvFrMxq}vLCM?mHir+8uJiL~q= zbx+tUhJ4uCxjbr#+@RBn za{!T9Pb!m0cC#MJgKM&F(3c+eoGu4E7<8T`=QC@dlc0O$&;G$XA;{&m_wn2|(mP@I zTQLXXuOWMF!Ubyr=Ue_XcQpMVC6Qz~UnpF-fD(4dZsVTIy8e%f4^yDq$%RD~CLW%+ zA`e8k52KsHoqI17Wu<}cM4)AMF&cMMh6&rAR(O_Hn~%aG z7SNIQ?TZZLO%Una6RzwPc1@m_PP#SZ*)d?&MY}&3g)u1i%C(|;>*+XX&yM`~FAka4 zZkjyEpZU`&sknINbOA)BN9rlexexxHKZpO@{OM0Bf}iCU*CpD7)`t-LmV8{j^FR9b zd+zABQsG?#V0*f>@>VLm)8TBQ<1I&;!lAwT!}tv&$daichbA|EdqD zr;J{;2w*zh9hhBFg4Q*Cio=maU&k`(Q1;Z_OSYNe>)4*UO_-vU0(R_RC;*sAF@CrX zloLhvHDaI9lfR~@@`Sz0zzv6l;PRD+6iFX-eatLZ6?r#f{V;|3l@D5AaxRALJ?)Xp02J4@^uqb;432x;Bp^j3z<1`4H&8p zI#P%nnMnzMOmOr7O}3PnD2cX=U30Hz|09afm?Tk`xVd)|{OD27BMi=O&mX06TEaE+ zTYvsPbXx$vhZnT+1~X$zA5$zgkSBFaV@V^RKs#L~`JDtHC3bGe^^F@c0|f7@T$PuQ z#6E~2ZSZ{qy>mlakp5e4NZ=>5kxT1vzVNp8#F(OZK~eYYPF*|SYkUCJNlXv) zbfx0MG4d9;fD?T~f}w(P$iRa~Sv+d0FJ4)nB`Tx7l>E(GyeYs&9YFYjd%ai;azw3t zP@q5A=*^LWa59~P^<4p4m5wpbh+KOlL|{yt{==RoTRSIIX@Z8OByX^;askL02~=^2&7O8ANoa* z*_YNAj>SqZRK=iUS2Qkoe^rTuNwA@C4?VrhLZgbJf4sAp9Yg|9Hax?%W32NIsSSiM z5m0uKX;&27=k?(d_lL?%kBIkhC?g2cNqp3im7p8Ow$jap2e{hB?nmcwvBjv~v;RFW zpeSoSY&Rxw&*mr=Kc8AJxCm$H`cw|4ltHO;4N7UqH1iDf%xX0^wQvcfd{_eHHlr0E zE|@Jo1v1Y#<5 zR$tfD3=dI5Qk}x;ms1Dj5p%g>Dmvb~t5gF#2G$gmcSkxt^aCjum~y;XS86l$U>_V+ z0$po-OdvGWsln<8MmS;!>B-~C=VCncfI_BEHN!irZveBIn#R!!?lo6A3rEiMxE-h&bNh%N5?yvv4nf5sMhmiQ)@ zIj#KJb(th2Lq~*ar+(P8isZfdPQY%+gS8h)$KPF)n#R#nYFvbgpC#K2 zWrC0j==5b5&^zt2N@e8F1dKtS+2zDg^;qvN`Y`xqksPthb$W@{$Ga z0I__{(m|jeM&gjNntgcnNd}8B!cRdR+9(~AkvzBXX2=_Sg&HN+Gl(`(kXWQ0P*9xQ0Mg5B=2R(2ZRmhI;@g^U!eN)7;iV?BqwU zC|BDeHO99BQ>HIN86Ye~(mvRpZ-m3l1R`^o*ZTAmq|FFZfaYfNPqDABKWYbAW!psJ zuWo5gbQDLN?~^T`bo^nG9Uo$xTy+lc-AVDk({l*nJ=%GpcSpHIoiaeZ;itUJf8nEg zONw!>_YjuzkJ7-mU8mF6zq~8J*9iA^@)G_JN4eS+NqzLfQygIfQoJ~q_W&bSIE+>{ z6mS$Cqtgz_)lNyq@YBYo5~jaWC+UtTx|oTynZAytK?`3G?#$Q~a7p1cwT#zhA0 zTrN?Vyc+*0T{2wU^n$4%O%omXO1-QT6Se~H)h{_i75VZAuAs3>(Gk$+SZaHot+K{} zkLXdQeFA~X!p<%iiMVC6 zDcMALmk*bSiC?N`w8%v!l5#HSb}R`-($8EXVxDIfy|P&XfUo_x){od;^wFPwNOb$s zui-_An3vBnd0O5nrbU16V<>(Hj(;JCHaGh!-q2^T5M~I^&|5UGkusCSB=Ii2cIu2t z{A}~M#6SGIJhN>+&iB*u*bm~+y z2>5cnv-7H$Hn)a)Q9jXT&+y_SphXGcLwep#PPBYuiAB-2KDFq zb%$9;CtNdn;>VHgu4g(wmXY#&H1yMgE5ce0s23XsAhIXj(=Mdh(5tZQvugHrxq%HV z7WFjbbx0jNskjB1)I>*Z?NSJ(stbC?34;?590eX8_Ue}yt{E;P5-ESoPdhjG%Pn*Q zrg!j%YMg_WR7KDu+b1pYFUtIhuA?1YYrg_xlAe}y6ZzoDgWKeB8^}g{GPo4P((k(L z0>q!%>@xf(k)SBi_etNql(fQX&aWUE2zO@$eC;Dd?mvX@kN3gaj>m6W99w@4kK4bz z3xC(y=lr~n%>bp(^wbW+rj&B$NnkfC#+2v+oKoHQ-2_TDXi*v#jB*cGEKA&mNvg&J zsySD1Qezq_K6p``nUyG}+P8J;HN`K!JOVj{N7*JRQR;?|CtTDoB_$;X-(PRIIY)V- z&7CV_iF`xJ!3ZCgd_A(P)i0?~qQRX5j?FxCaK8#{n-FQlZ1CCC zzoTn+on8WS6dnBdyeZ2_`{9ak!w5{bguhfW(!)gZe4s5{T79_c47h|j@|r_)iJwff zT=h*?W=};(^hk?L=+x%Ea@9B)=-9amZj2CDGquFUMXuw%^9=}+7Hrc|kX>*IEUC}K z<#qSyWwHY@+g5D(FR1!k>ir)}uJhkyRsdhTsM3aBt8jZ~dD_pTIv#oE{qIkgfTT|o z`!2jhijZC3nR{RpR;=d=O}G%`21}njjS-URy?fF&DMyje+ldkM!&RWgj?f2=^wx?8 zh{^vg?cU{cw8>$5eQTVyTHw2U=J#VDunX+BgXQn%_;*tT{%($cH$~v@=JA;hh{*?nZ%e1m!M*U$@W1_OR;F;_Hw?SN*Z3O zlIoaNZXa&hc5{H=IZP=nfVv-1s2HS<2(dG$c;#71tl>J`&01AN2q{2$=O;Ih6d`dq zYYw@(U64-4#m!?X>H+SdCn{T_#`z+@bo3>^iVnM_D0O*}u{%McAv)9ZB3{nsB^2zO zt5SC}vz81JFszkJU_GazhxR)9gp$(+=g+>q+(e_NYq2v*wa(Vti*Ox#^b8wbx~N9c z7bO zkHN)j#0jPM;Vk~lFadsT?ePniuPgno!AX%<7|-+o zn(Tjl;lUEc$smf~$OPb@yfFXkeF6T-3-iC;7vS$-nEI`H?@x|&02l9eZyEZgulXAY zA?UFP0ssI2|Nj60AphTzC6ZV7cCIz*ma?92NugaU@N=Bx0JD&a>vJ{o6BbIO7&!Wr zpmH{1Bi;2NpFv1=kt*@QFb6NsW`hZv)kPTdY%JD+ILJvo+S|jedA2Ol_0(-6Kn*v* zBsA&UNhkWdPN^CubJ2||!EI|nvQd=}ZYhQUL^}l@j!_VB$AcRk&*y%18sLuZ%@k-H zd(1l1YmHQ`VRU^|cPLTR8ia%__n{=FA;inPL(CI|aIei5R=Ndn5+_Ti4 z!8C(wcvBx6qzY>HDyp8W-*V(8qMp!&g zf{so+9US>T^#&n}T~TE}={7hp86P!|M+{+^IGfb4;@?XAMr7Hhyh=sg{e0{DCI$YB z>*u}5?Em5V*+W1-TG;VFT|bNlN`FhD{;s&PN!q)6zPo=ulU}xiCXIegdink${%(rE z-_7ywrU?Aq9RF^L!1p=EC9V-!^zpcOVoz1bG!5r7xxhC;rX&3rM>WZK?m12j9bg9I z>2(dHR=h~`7=d#K7uDLkN`M5RpjWU3g=$)}I5AHLB)Q#2i}L6mE@rP}9-sh3seZeX zxi+XLo@3EtNM1(LuENglMG0$)X@xhD-uCCSXcDjbEw%4ER|OOW(I!&rOXDLC%}Ucv zjPWtnn8`n=S^~Z#di=UoC%N63Vepd1&yyS`j|EBaZW+)rJ)Uir!SA=jgQ|g4E7=X9 zUfEl|jz)O%@FiZmI$fbjl@#{CP}~DAaqB8b7bA$)q$61UESIUSgyu6I0hUT|>v)cN z1&8V~)aQxCuwjia$4e|ytz%znLy5irlmdtEmi_BT2VF+d8HN_L-xhObp7o7`?(Q3s z_EsLX3w)lQeD#nS@PjTBTaQ_%Ltu6l;KKTumL+6-oObX5TZlCY#nE z*)&XAk?`r$XUQ1bgB3w~=2txbg%N?&Xoq2|X44>e1jqNVz^2f^nh>#JvG$iQq`9-S zZi2bIFYlzeduFtW@9o;&4_578=JX+o@8RwP)(B-4h(yR&Bs&X#5zAMiEz1xodR|l$I1*B#au1 zkHf$`WFy?Mk3h1QV;1#x<4bC-fdDB-KEBAg=(H%+Y7=C8zWMN}m^(G;4HN~Bh~zkZvaR0XGhp}F zbnAje5_1G=8hkYF=cBJ9rU+)MMOP?!=GgQ2>NY42R`5XAk6R6<=Ou<%O<`j|-IV|E zSv-P7Q*8dJc%=Vu3%t7o^zuD{2H*^w-glIQw=79Mh$LgMJvHT5fM}G2aq&EcA`9&q z-xfwaqL}iawkgQvcLtt6pZq&!OyJWGOT<$Rs~y5vdV3_VwbGcGn`qr}@;DmRZ;#7$ zXo;&{skyKq8qA23jl?ej5U;S>GSKC!i_Zo_(T+}~9t-`ko2thoAEfDEXBu*4UL-%3 z=@c@ECi(qxgFx5!6%X*l`Bk3TRwd3prz)Lr7crkeNDLFU@OzhQ_RW8JvnaX( zeh`A@Qe=TPWrE<3F1i~u-h)iT?vgYYwBJ^M7EAgek=bX#MGkz}0y`ks6BvfjwO?OA z(GP|QZ4+Q0G8d7k%^Y~^gt@1By_e5u#JPSjLhM;;|FCa5@Rq_O z&c`#8gn~jH8nGjjpyrG5fupL$-7NJ{W-TbUV03sSkm8od3ULwfU_64!paETa)M#BO zN88rC>~N2?vqG%dptZL4G#4jCN4w3=Dsry{HTLgfSyo)VKsNeF&S0hhtJ`gceM}EN zbtgLb)oO<8aLvfm4>CZfVmwSKb*SkmL1yY@pe&(EcIn5U-zJvRW7`@Ka6xICg|6zo zfZV)9xN{N166d@`baeGYMImk5P($Z>oYLphVQiLMy1>tGk2}Qx(yUi8PGR@>G~!^% zXp9+AsG$WU#oW6v5?>an2T$CEOf*b7VTGXHI335j7aUjeAi%y04~aRFk7HP<=3!lQ zR+X&PZNU344T691v{Lr%YQdv=O-MkwEziiY+}K-U+gIz~xmy3|X~jVn_=DrK%@0j~ zpozwfRKo9L+`!UHJ}a8jn`0|=X>m@P;mA3_;222pR8aP^$(7Sw7c{4w)b$R}C%$`u zjYah2hVI!UMd=(NU5!)qNn%{q@4C)NeBgmWMXvh#WUK-|yWUMqo`SAG`io`p@luzP z!QXSpIp$S!soZ;Zlb_9PKv0{RDT4|DT6l(|>th6x__rGzxWi*ML9Lg)Q&sipH9HdC z+%!(jEp3^eST&2B`-?eaGtx_le*m-syX9%E7fwNM>sQs-Ig3_!Nu2309^}TYK3U6xR9=X}JA9MvYtnn}znH zaBahQ>E{>h?bEl0Dlz^-R>o;>Tn--{hUGntz@&Gby~>pSUbejcIEKk4v!@n(Px;zg zoBhm)*rY!9IZSi#v--Em%@NihWA%%hIipb;55C^}?UpQN|S6zlSeSW56NW~aJJ&(i3cxi>;QF)t@*e9^( zN^)EW5<u>=g?i z@D-vbbNy@DE$~medh{F4dzQha=NcUmw0g+d10M=q-f0u?HC^@}Wy{j9{5ZY1@Tp>x zrObe#O6^2|uSKhfL#N@~&A30nN-bA#Q;*O%hRgjr^0g%0wIzr71ETrdCNsy7=&ke) z1L-hACdHpL>l*5pV@obDJQH;sOEx!`!-G0a7QC)tge@HrUvPxe(ZiTQ9&;z@Illm- zI>9PS$cGIwpi7)GGpFY^=`BFG7`zQ;i1W9Iu5S_TM8BT{Q_W06i4T! zl3Utq@3Rs2xZc9&dRwK^d7`j&u@13!U<0G_tg{on;6v(4mUouH5%o&}IEv?#%)tKw zMY+d@h=`8-$-E;iD0aRoH~o2Shq>rr_AkO3--WePl~H|N0pF1_ z-+;`du9~pEe4z&W$mcR~@I70AM?YllEU!P00sBFT6{%*U{~WdJ~V?r~i(%pbqd5Vcc^ndDa>%q}zMO zkAEsX{#~#M_!4az7M!v(ca#;J;8yuXPX^P8oS{)9=UZqxsCSvRPKW1#CqtDhWQd1f zz)Lxrbi5E)e>qp}>V&h)#>h_BNTm0t*FZ=RaF%pA4NWf|Q0xMCje)+%brDhDb`O9k z^-)*Y-HZPn&1Y#)>Ii1%8W? zH+>sTA6=EU--F#v=y=sK(ROR`m!|Uh-2T#2{`(ZRx7mW) z@lCt)*_X1pjNiAf#cjKj#y2fN;&_Y`InJW^AtP2?0r$UQT%qwWBQRh;;iM4@&S|)> z5k1a=`{xN)?szm&9nNO&f4`r%?w{}Hd3ZPx4S=&W?&DOBZ%c@3M2oW*Jjw8EKhERZ zs&MUo;`W7T|Nnl!(WY!cT$SGbANb=5+YqCP==M8W(>8+bf?l@Wh@J36d;fc%+S?SO zw-YQp%C;|TbB*zR1pUWQr~OXV{u%5S;P`#+9Zt3T@fO(cxLs-54~P>!;#`Es6M^6) zx?KPt_NgUr7moHXj{ETdCm@`>>>~>RoRM%R!$*nd_|HVZEW)QO1h=0@mW9doWBhT0 z0l(W}As-NBJ>Na|?F;=b*8j2(Kv_}0iZsFGr!VralFE0uxF6p{TW>{0*=iHnLlHRGPVM&l<^VkFyss0z z=^u2;ycYq`Z1wW%EB@wccg{cND70bI-&zbjV-QKLVDQ&}<_)-N67d~-QmI`YcJ4mq&Q;vVpeRGG{^d+5tq zuk`6$J*AdQ9|5g3rz77XZqh;NSVFgmo&^Ub4-CDnH>a)mtkqlvoQI|oWGh4t%#A%g z(iu9UNzOfJOv0D8^ZMjGP$$#0A8_Yih_ zHmNNrvY=WA*}iXfYb}JVk@APDa0yX0;StgqSU@1sCiN|8N_08n0=nK{*#+@$ENsCY%1XDIYK8|U99r>+ZN@N z_Ps^9Z%8`7SNFZsAmG*ZaH=73u3+FwU$Ckqk)J8_FqZFLPvFDtxo7`Fn-w?7?^I{s zk4-Z58~Vu-*MQHQ4ARouz=5z3(Yt8<`AXr_#D7F=H}UdUpa=Yqv?4xGIRP4iRpzWZ z%g_BFo*%A4*JqvKyo4=M!bbs(2MZkS<<_`JOTtFL5xGt14c2$&>HHYz*fw$VG8@Q_b z`ML1AQ2t{BY|Aq)t8Ry{NOHYjl^s*1!^^1)Smoy|%@uWu>;Ea$0(Iz(+x4j!gIdj?FK zw!Hr{W0`#+2hFUtfz!17o4o5IqBYX%UoU`ja-utR?uk(z#Fb~SgS9EJmyRP=A96Ry^PO$f zFN{i32!Tu)d4(R7-T4YutI0S`zyNCXM27eivZkgSZMkTDLe(Q~JgTCY9zhl6G=j5f zLpd7~o<9Pu6;seYh=g)GY7^ir+=ccx)qCg01cTi;J-AgwIu3b!yui?X9ZX;RkCCNj z?}XDPKO#%QZ~dvncNUrLQgj4JMEeOrOr5o%n3KzZwKAKvd*2zx(0J>loPIeVE}%-aKBd?`bDgYm;)90SzO zJ>06&=uTf4%_GVR9v;ua93(h7ozgZaAOn!){&a?B$cmrgW#zDQ!+KJ$Ta2Yi2Y;~7 z0g|$Kk+o=WGZM@syo+zjZsKrt2-a-`XpfPBf>aIggM%qdUUPoF2+RfAU1lAlvCQLd^PQ|>WQnS&)N`tWMtPBNC4(&B2VzQ_)eg){h6TD0LWPyc+(nC4!C z4tOnJ(`w%Rni4DER51Bn(PrL5!9I;f*?KUv{A`Lc%EziIQT4_Y6k|e+X5}t{T}hOU zmlzV~16qvD0hq(5C%+8pti;uDzLw4?vrm+@Mjq&DxwmE}$EaOG6O_BWaT-^66Qhoagap(t_NBl|ysLY;?bWxw@y zDl6?tg!dy1qiRT1>{+kxJtf||Pkp1Ap%O>f)$xZoc@LTZpHY*aJyrNw{_M2Hd=TpX zdhEyD-*O}W%iZ^zzu8s)Ce`R56_-)hH9uF67g@%DGpR1a{N&2ko#{rY*`U>6Y}rPn z2l0yOsU5-yslbo|rH)7=W^4;oeTITIb-;EtfX&V*j%$$Ctdr5;nZ4CU2>H0N&Ki5A zHhYRJ4k!GKK0u7GSXik{T5}b+5JSXPYIp%SamXgx7xB%Kc{UhZ3wH9>kiRgPEI&oAGfrE3Q0t3=ZomoDSdm2JEh#mQ&xm=@1ta7dM;Li<2 z?#(n9ITAGAcOwrKM0--a1?pE9bT*GQQ?MF#ywOQ`PzX^c@-%^TTlI!K9UwWQiSi2OG z^)$S41Dfm=KYn_G6lzazH8SaePe5K^zj*ef0-HWEyN6%u``_BAT+4X>;of}HZ^cKz zC!r-jy%AdCjOg*n1fAB~l$pHmNYz<=z$Zp@3HNs<8}QKpz&THC*)qCP`KfT=n_$CL zRy*OlLKU0LOlI z%VnbC>RWO2JQtgkKHrJqc4>a!OC|YUE^689PZULFQ=q{)6xMMY!}JG=+NL>hv>@7 zI`J<^ED@&Z?JwVDsv4^ zPI4q~#2vl*UvTF{> z6;+H6WkxNRytxEPSq6vDCJ5%$xiTc!%{(3gOrq)i)PK&Jlb`RA2|cA;z%-2T1AV45Nu}Y>CuUxsZiA-TrCmAWk)pX(n@m@y zQ>;a7MHqw~c@2iMDsy2TQJfr%PC~4{sY8mXAaP1Uvci4Q02&kInZVL;174*jXe$j~lkRyYW&)+1V_sg86SY`D zOg<}4$cZ|>?uEbiNAZzU9n)Vs z+9;Yw`%BB=xVDoDOrrLdK`H#~yJ+DO9SM6IXk@5R7IY`n&K6!NO8~F2f_YMb1egFJ_TkG6*5i!oH^*Du8ycsx?PGp8 zNg0EJqf$k^>7=D5Y(!(1ZhhR84D}c9d5IlJg&p%i z`El98vPO~|n>r&)YBB#S^8XiVrDNq=L6}`7|yOM+>#SjlxLl8b?DK2YT zmEBkPEUS)$g-j!H7${H2v;0B_l5XRdcnICSpO*g0qEqM{*mEXLdK%o?CO;tlmA!vnKcA2R7lSigFBBJHf>1;%EGoyEBX^-jO&@M1!pO z8-qPB>~llmFN*+LSVDMfre|T$Yn@giY+_4Ddv!~m=v2+w1&EBEO;-xN**r@$VK+u* zIgvUSp>dZD;8<#>G%UMYJj0JDn+}9NXOfr5_Z;N!Otk6HmgQJc^C}ucFwZ#^XsN4R z2d|WVfLDO+pyJuW8$L7=#J+3O35n4=QcAJQot1Lw)sw;H-i;ks|8mTlp|1~IsQ11= z9IuK=1I{%JN%KC6EZM!$oFhE1 z+JORcSv&B&ix?&NY*g?;W|e$uIh6LN|HKN)?Ea(UkD4!n{(W&Wi5vZQm1zKyo=wb0 zYa0r`a=s&+{5L|aVce8-6|(nPUkT>ZF|Jl7HFCl;aI0!(BnCpZ8Y0;4dCsqRMy~=G z8$QP*woVFA3zNn^>FqZ-QhjJOB_00030{{R3W z|KHKOSW+(0MY+7)$+AVwvOWqs-f;<>|X!Cv9lf z_^hX-nVpT9oJGRYtp4+&nQ>8IU~fh7iEM%m8htV@^NgI&!nOC@hVC7e?%nNYUtC7r z7Ez=|7R;pe6ZNc{j?q7k?e^X68;_dJ@H4R29DHQ(NE8@XUei_k z+zt3zdXC)(Cc{az^$Fw-_P###&?U}0cQg<<(CTk1zLQCB$nF`|?<>4bjfiTFX%KT8 zzA$W1N{n3r+80mUVAbcE0NbL>21T%+E386xzuB<6?fNUx_`Xl*VS`Wv7{c=y)c3c2 z0({*lx`VCTQvs**yiVt7zmu(71EHH=@aQxJ2Fwhx@xJ)L`|2}m@`fv+YMWn`)c4sa z3I5a7uGuEl&?4P4I$Cy&J{Ws&%@b~lU8a=(r01%WNUn! zHy0-fJ(jcK)QlWzVyK2W9N1|OW!rkxsF!!3g^Vmz8(9iZ@Dp7)aWc^sG=zhd8;gZvbu{@ ztHq%efxNbSI#xT?O^_k71WTqqeL}iTj5PY+@h5M6bVH}4V;W_3WNSy~@T9h;} z7giyb}_0QmK~jkFatk2{^x8U0dRM z@=7FmN?E8pwzp;EcqQ9rr4xkT6zV~L9&Q`-iV}LxkG6r*MxT4RNGRJ*6orJMTeB%B z&%2Y)yVBi_;?PqXZ6ub{ifH5qQd#6tH1&;(Db!(^1O*HZJf%xm1GMr%fF7_EKO}R) z^!x^oekjo#S@2x$EQ~-0-B=#Pgg3~v(4;1X3HcyZ4+VtH&gy~1Uo`l&bXvI#L-wDD zvngv=k>%@e`gaiGH~UvHS2_kHqW_eeme$x<^ww;iAgl%4rY+5KDXmf&&76scpK^ww z1t@WeO{GYCd(Zjp7wMg>a{fY_xfexlHmx-&Z;@*H`?1MbzZGVi_sf?%wZGg+v!y{X zvsE&^Ra$vO(!q(H-jm2FiqOf}ttQWv*Uh%=-##h+tykUO)!+cX^k(M!3jw;`bvV}Z z<#8%4mC;dna(Wttu^Y|ZE+&LuNBQn$GkKOG7YBj1G);Lqdx+T~;)QzNk~{*RPIosA zj<1@-DvwPa9GodAIZcKu#+zRYx48Iata(**feO0Jt#LuX=lL~0>fu2z3Geunaw;yD zsV)`S_63O}btISzW+9bx|Lii;E%8KMW19fDlzhF&dtWg^CJWjbe&HzSgR7dm;C&St zTz)_|$5WIhQ+ZoR@t0#Hi)-FPqs*mZioPmY%ghkrQ>Ih7dq%PHVvIYgtTARC(2J}D*3er z=X(?z_+1!VMd85l#!G^{qV{w_d#V}k+_qi%>@Trn;9aWysre9Yvkht%&!#0#vM8*# zMH9G%kC}TOVr4LhDv(9I4Y}QcBI{nB(J1A7qlzC;x+wY0jjP4H#Sap59xwr~`Tvo2 zC2MXX&34bLXn_PmNK0lAlbDAc^E}Ty{Y7P$UF~-F?Z12BugZvm1Z75?$cQ+{JLmS} zx=5C5I1*@&)d?W^R6#X??T@({&hv<-2vdjdZJcrZ%H;R;w0YU}ratgM^(zw#8JyVHR{TH z&rL1>!MWB6!X-@@m@!CAjEtT&_CCiTlQM#p5{Q;K8Mf6p3|-_CsB>xaU+_KhHeUDB zPu*Ysu`B5&huEJM?Dtl2Y<=$-e-dhn!r3I$?H3sK53vsL20I^|K%e_+1VSrC@PQh= z19^Ma`452cxXI>eA5i_{qHp@O;Vss|QPi}$*Xh?iMkD{E@jS4u{#FR&R*@{f;osvJ zAnM9-Q2aP3attQw$s#46G$)Ub(fkr9`~i&ve+$Py1haks<4HB1>^rXUnVPPla(st0 zz|WXwJy2!w0g^v2`u%xvVXz|MS6LeRom1vA;4hNO#J8j}_f9GkZ{nebQ`0lqc5aGo z5J_F*TT~-4lmgdyvO_do%PG;z!XtIm-)#74`Kgq&3Zq`jncmGH4k1YexBCM^3$W{o z3j){5Bg6_|%-HU>$p)BJ;OSbaB%^t_(eyjEPj?;ild3B8SLXSrAcIokW+TF#Ap*YR zTk4cu2Vi`SOqC>L0`q+)t6ebErK>(BJ~@TMDM1lzouaX|!7%P4XN)+^*TZBSu-3}U zNf&^yWL5qNrOdoiO#zEh?KPwhf%N&FWi$f5w{6rd{@G^k%fd;`-m8`sf_YT;2H!46U znax4UG?;?Ueb(9}mzQh39k09bxc4tjkk>rZy9p00->bjz2A`?I29Z; zXf{pcR3%;9dg??W4t+QaE_LGvH@0$Lj}A9!!W0Ekl-hz3XGK}P6yJ#UECWLAJ?vRh zGiPd!0BN5e!)?tJx@@0ZS4BrMI)Fvw*m{aH)zE_G2`f zZa1UkiFgm5zcaDt+MGnQWN~wlYra3vF&%H0(LYN~;h%_d$j}-B$_G;jU3VhZnoy&1 zvERwCC+s$mxHx~=cmFd%2K<$1BXUO>9b7CI@o!ouvWueC8`MWo5&S`s7JRIEN0fUwDL@{aHOj3nLIxrweG7uExBCfpcNw0>}dGWTEli+hu zu)SD7EyDpfM_OR_W#9a6hga8ojcBsHW*xMa_Jo^E!z9)Il(fF#@B$(E@ZL&V1ZLJ) zbhA#%fG+U(n3J+)fS#pZx~Nm>f#a&gaiK?SD438>!%{c;H6ZZYwXk1!++)qMb4T!U z1oFTVPtWJe^H_R=Uszj9iNT4!JVO}W@DqN`VLh5?rpTEkd3gdl08>D$zdV#DXwOFg z+UY(~IRNKnC_T$9RX)z66FK+RsNh|nvr<+w`s|gw2*!kPy9!NA}cut%FrJe^|GZ!?RZajdH7? z?%q0B2_MQe=j9hGKc>XF$~d>>OOs2=n)lpchR=;l#sq&V=jwrZDGNsi3MjAg!Xrbk zRvMG5=s5=mHhhqs=5ax8az>kU`hSUg$Cpax=g`;T8BsD-i6HjdD+;lgDGt^Z3-62-yHE*bKP|d8U|LWIhyY#ZNtnZ z%r7T*6_^paCg}~q4me8gA}^6hOAvi&G{$Y46A+N%m8z(wlX5iUy%5{>;5^Jc1Mq%5Wuaqn(Q{4)u z#}&qofW_MK{M@elE9cpYXP<@!+Hkk*!}ue-CZsu?)9ncexqUyec8JuEGJC0;E*8UOf6DjA*^P|ok>{gd zEDuG~6x~}DCYbKe^NmTbXW|Gm0|yXm<*qT;SACw1$BOF3)h*0tm9$w}@>FTnvClmDUksD^-f+mFPs2oMx`_RLQwICB$Atur z<^O}7ibzFTIU}-Wh%2>Y>SvoKQM?OMOOm6XFa4r?Qk=eP3n1YAi>y=MIZnSF{BbP* z^BsS^A@EP`_;I1MM0h9e z^4KN#ULi+}*}&k7<0JUK_xy&`!e=pQu;c5mW%Iz7y7^z&o7D22Gb2C8Fl_P`F$Bb- zpmRGKDD?&70)Iy?1^$9>-I!Z@t%o0vi&iE*iw%?vpf}%?f8VP8y$OG~pu=ADJxKZ; z6qouaye>loUxKzdpameyJi^SU2&t|ctlp+uZov;%R`szZu7PMfG`XG4rJ5WbzEyBh zb9#-zh20~`qm*VAm=dy{ggb8DY4}*Eq6{);7RwgUWRfO?yyH2cs)FEk-;iryyEJ$} zLH%qt7X|b1VELH7$s_7uscDrQIQSETQfj zQwyq*<^c566_hh%`FvH~SR-=YdGy&eE3ulh<>sE4XNyl{n=XwfbZrk%id5D5-z2M= zH+pD(lv&~8?{}2R-_Sw*v1nhb=*6*+GJuRkg&xp>aVFm~r$02UucD;b_~J9)N|68` zLVmW(f6$S9RGu#1)lb%6kBOA{YkNwoeBqVlsa4_~8&Cb}LvfY$;kW)PGP)M>l?6bc zmJ1%R_&Z(TdAC;6M}i%t>u}BHbHyZsRr66zV?Ku{Ehw zx=V={xx|7>#LKq{zX0oGP>#m;Zmz^tF=^HU` zT_SCkq@YJ|Gb30~E*13=9D%5e1UYTpEC*si;uRGSjLKi|?EA114OJ;u?Izw`o>UB* z&yIEM#m;3WP7m@}Ls>ckibdsNos$z|757Uw9RRL_qR@eR_f$LPRBsLMBX^S537f~E z`*?pCyn(1} zCd-pdcE|6)5Xs~$%fxsbXpeux`Iu1uL*nflE!bQBg>_+>?1u&l84|1nyvtFq#n!z> z2WVuTG28b-vOOwYs0Tu~77)A)P4WZ|*O{9#leay`5qE;_#9XUc7Gm8;0+Pv2otOy5 z#u!Rng|~+}cv7#*Z_W}2nW1Q&fQTOsFbbFew1lZSzEXgcsNPT70sPX?=oUWrjft~jc?OKvJ_o9&jO%_*(EFv@H8Ot|-s?2t zb{bwchPR@2+l(PP49T4HeSTAo%K1nYw@3ddyCLe1J_!$qI`Y&`WtZO|!)m6U< zbicc;mQT&?Z?sv!`%W@}|LNop)$8i9amO=yx)rv@4f9=@H4&I3C z*O9qN6=5X8m^#qv(=Zw^AtxXu%z;6T;VX_&a{0X zl?oIHbn4Z^sEtmZgl6K?*f~@=yuL>(CIDo`Phn{tQFU~B6$NhWkn>a|=t(!>C{52> zU6*4oqA#=+d5Q+{Zte1cRUU~E#)tm{()Vt+5&Ug}@h^k%!y5p9sQ(mIWNU7zo`@kU ztv$5Ueo0xnK%RB9>DXVHt| zu2anU2jDv#NxFW?%WlI&M-;2jHzu46c zwawp=#*@F)CVUuZ9n*gpXjW|;J3PDEw_Yb9rw;4qd}7*}XT=T?^N#hTifxAo|HeOG@Y6eoj5zsP4 z{0Ez>_#QRzb=Y6BlLEEfe{vUY_~Bz{IAo0BSN{Y2l><8bPazWAr~mOk-_ck5`$OSH z`Q~Rf@tE2a=CE%&yXWWk>ZSQBMPUR-ItfNKqZK6eWY#gQMO=K!QV#_1$d8-l`688= z!D!}~)=y2)_(I8R3T(h`3z*Y|g25W@qH9mzs}8Euq}IxV2@~(^i?^tF!))D*}F(Ec&ZlQ8gx*h>^7ipJ+zD3FC0% z0rHioSO56B-fTwSo}GGoSx>D4c zaiTGDuEPs218xPeQYU5*bQ&FX_vN^Vs7d8(4~&Np)OKPWVeZadB<*@>R={>)zVFXE zZz$69GBpU41=JimuMOF-GRpHCW&Fo(af*Kalo{{G!b7d1n_T6#1{*(1OF3ceSfco*X%>|97gQm*L7F{NidvdcAM@u zr>=4>_egq`Nhw2K((2aL+F4fKIy-pwbq{_ z%ocnN)*BgqfU$a~M#A&2g6j2D@G$+{9tc8J zQ+b%O0uk#C;n7>SV#^aGP8|8NW7UI20>md!;(}D>mN3_YbT^HS&nO(L( zANHPm@KjAM0GpClx{i0Kiqtb(mc#`ba!crIoAb<9e{>B{s6Ke>3n#11Ox{@J+ zw|LYkzw#k5<`@`3mj9=iS@>D3+F}6oG|L{Vv@CFt2Yv+63Q`%D%N3rRqVVThrP+8* zoii~#y5skbUm_lZd-As5d4c9Epdm(b(k$f#6Ro(Jqj~@rd5d4&Aht?6$MSi{#9j3j zCj-50Ec-2=huJ2(%9o>yKLO)C7u-AhtntP%{@b!p+Pz8F)11VyuqkkzP2qo5cl2KWpgC+932Ai$I0Wpd7iD6N-F$R|B2FQQQuys0SVV!VS(GF3zJsX67C&bsdCR zHSdElxR@Gcq4~+`244Y^Ra5q8rERf8SS6s;had6 z^nMjaIpA3JTR8SV#LMq+8TcMA!~Z5;euvAze~Fjh;W7|?;+Rh!d!1UoZDjt4mk-}U z9rotW@$yd^sec(SzwIz^V6}f8FaK~-|2AHJJFg>Z$Dy|(&T<=w;vTxo}UDZntV2{~&p zV!&q<7e5;a!sgRi^J$Bu7M`$o+l2B-@Je8O3ZqYK@$GRTGmpD#=S*dfD?Ufia){f5 z`+s6c;CDgfAA1PRSTaM^jE8dQ&ZHMF_yIIelxdr99S(pXzCHU}4jF?2Ok@;7WHih2 z{Duf`!Zf#D#^no(u)5min^r7@1CE2e=e|%dI?yR-Rfo&U3VhP8Nf1RWD<#|_m)=~} z>hPE+@=CsRfNJ7h@VwSsxScbB6zrF%|V@kw5qPcj_xN`S?5F+aG>MhuM3fx^s}>>E{fNDzo6& zk0iqES1aKUe*K?yi2n-e{sPlIeuL?3K*WttP$!#}xp}74 zy3q9#a;@z53hTE?q`$n-Pl_RcqmVLW!(&LpD(BeshyB#PY&X(>{w6+62=I3{Kj=~aEzSde2lQ5mg6*EdC27nqtL1~2)XNDmzf^==gppEl z(hVsSSLSvacuZ!I`Uh}`=W+IHZ#T}^C?;cYvsuq(Om;8sL!q#>oXDr*!mk7y^A__G zvuBzN77MV@O^oTg#nCi%w(*yF>T_0piBW_&5QY-N+0qwcud6iZqXmPbg4!dQ+OM;y zF!hNA1ObH}aY$Sz3rr#YX)m|{-|Y}#O-d}N8(Y(p7YssZINUktH6F2*9h?w_8H=0_ zB>==lHFEUPE_FzH-Z?B5m8as^+SsqG-BuowCT^#@=!2V*nO)GO?o_cby@@0J{G|i^ z^I>9Q3=vFcOePo{wq#8i60x>G9bb!e??=mPurmM27qT6*a{f$j0DsDF{Eq95Ie#Jc zr9}Lg$o7p68+up(OUG@IHY~zAf*>m_1t@IY9DD0!FZgnV{mYfa(uSfrusp9F({qsQ z-CwVS=?x7}1|V9CNhA!5gMRSJ4n7plLj5uG_K)fNP3jl|00030{{R3W|KAFrb$-ih zx=>ktCYOLu8j}!gTaAihV-?J0YFM#$*s~k3%3U?(5*LA~ zEN@?(`*hXui(62KRmGi#y>t`xns9?mL|@$3SMa(xCwT|18~c2cbqlIyrOt{^g}4;l zq=z~e57bLzXVljhm?t3}^vn~&M^R~@R?w$Q$Z^7y zPLWJmqlpnk=Q4vNxLhnQInOiha!e5O*Xk+504hR+6H`~DIN24^dij6UoKN37g3AwO zIz_mWC+@n)T=L-Dm1_zo8iwCM&@KNR1pOZz)Z0G+|HeTbknM+K1O6umWf+UHe0Na$ z`qj(fr2ouye z`UwB(1-{=O@Lyiw_iy3fzrgqV13q8i-z#8hwOO}!V{D6RxsJA!M*Wj}fC*axjL|%3 zOcG8NR&!ECW>$SOMbBes#N;bI!e>v?@@b^VwS2k6;VbJzWSG4#&v*;Z5fBUfd%rTp zIB$ZQ2YTkJQCBZ+RWR#JMHu`d!)^9T^{ulCiOj#&L$K%F?5^Kj@ zkq#D9b)N6O?9_#f`NQZE)N+6m_9tnEV&o@VXBuzF9i(6GC(IjFjv-c*(XPu=b#lOC z)pI~Lv+&(|hi}AVe;}UkLdov#GmqNeklM3;f#`y00YwZ?ZG{%2hCK6Ycs+d7fcVVi zyH?&8h@Kn}-8dk+lahE+IdpT4E-nFF`S>n1s#<8+5Ed8m6)0g!yp&#Y?~>xnyH!03 z4EB90C0OOwDet}7=kn0V$T{7F{_O=xuLR;cxS6)W^2<3W>t88VTf|R zXf9naET&O2TKLQKi&0*+V1*|k-#`mIJbT) zp?n{E_p^RKb{I0C-Tzi+MEs-9h_O)1XA#NzwpAkFL&x(`V|5_BHxI()vw}n@)zly4 zTX2`hkoC#NLJ$usQ&*ICZ+kz^xA+?P{T_AkE{fVe`*ejbZ~x6ga6D$he{YUGaDF)Z zjM8$HPZ#!|@A^L}C#{4U1t=o;s!leso|gzdz4?XNe4pG$SzPh%SSQW0HLsi#+5AEF zI#AMgFQ&(F-tkvT#8ACHp0nt=L`!ZYXoAXBft?E@M4h>SZ0qdK%|`=?@i}#|!+r-a z7t2BFx^y<0KA~5QTFSi<@}~&BPIOCxgOEQix5NBDRgyq`)AGE?9I=9haio6?2w-BD zG7Jk-agRXtf)0-cUcuX?05ih7T=pL9oS0y=JcC`cSFb3~U{ku;P1oJywNe>?6T&6l z_ehf_%RmDpJSpCF2(0u76RhooGO9(Nn2LV5Ro%thxxH0To4oG+)p?lg3IX_Y>`w+B zVx-OrZF#99i^FcMbi!VmQu`S5u6yD$p*bIZXveg#yQps_P~bZiDD_VgOZ%&>3y^>& zi6|Ew-3<^D0poEZFNpKkTdDjAqUmCF?s7L2B3W>X!@bBwsym+1>JhHZ48rgizK?IX zLdb>yj+dCYHyXqhiNgsGi(Ogfc6Ic;PvSOf^wD!h*>D3rMJk8@PQ<+o1TK9J^k%3h zQ4nRS5G5~1``3dH%Ql*vb3D*P;a+G>>inyjiyXOJ+-uCMI|2B|U@a3;tbJ-ooqWyk z1>9#QOi=i#R@bDR%hd3jRDh>btD1QeYGw*D(G<(i`wr2-B;@|wTL>T5o^;qe%~i;h z((Cywt~+cA&yYR0m3}E^ug9a|aq|p8sswMx+*oQR2(WYJ%Fko;sM%O0yl9mjsqmF4 zbS=!VT0!K!#pxLR?#|9WsClSATowIKMVj>X-bqD&p!5A zR3zfdXJ@Esz-sE)O5!r+_TB+_|2*K$bo`t|ZCLnEbqV6BAJ#K{=VXfyDe(g^9rkB% zETnL)>#y0E?Ppz(xJe(THCd%g^JcSu?{FLk^>?ybT;H6c)-M@6y;xQ@$ATYp0H$fr^l1NT|#0T|cRuhi1dsa_{w`TQ`O|Y9JIR*!_h~dx5> z!$;+=wZJ4Bab}G5Y|$JF!rGM~IK(d;hseoro5q2RI_ZHFmew-nNfo9zfn&*lkSmFg z^UDBSWU_7|YOhJFpPBJl&T>vHCak@J60wOv#FgY3NnmL9rS?kYXc1Zb)e%SVHQmXX z0$MRv9=3974`fQbc>fs+P>(6qt2Ay-mX#68Ej^gP%gEd=dH#6FkEcjR?lYsgcfSyT zsD2GUaT8v^MiwDg+US=Z8<`LFG?lsueX%#!@~UKbaOCC0vGK9%n&`{kYx11Tcb>|C|k$T2G z(>u;(W4|jGPapb=#yvIV-a^nCWCi#tqbj~whtKwzW1ONwud2#XJP=6;zn2!shPFFi z{Q1uMAOTmG9);1)s#LWNn*>)N)|bF(s~o8_l2h|coLnwY$-4pgEu7ZiZnVeK7rE{v zv3+MvsIzetYR+eLdIiW29RW935?A>vO?v#BkI^tn+wrGJ1q@CbA%|hhYsVg66s8DF zb=FS+4hV1vha0jSU}gS5;f&e31Ty)=WAULQHiF6npFFnr#-3mw!4*^Hk#>34tjOQf zeSfo?{-hhR2~5_hvoU4{DND||GTxmg?>{js@JmS+@s?dxjJD?6Ba$!i=^Dn)uovik z;Y`BBRdjYLSEOC*;D-(~2KnG>(f9V`cM3 zh+UV#)<}ywabui&l0-FtWD#Mlc|}5~YmhfyNt1T%RSTpYrNIn)R+c;lH63*q&+ySu zH5jnav@?6%Tl@Y%0nV-B(!C>c;RODxmLg4|KApr_4vi(_Yw){@9?sQz6E{85J50 zUbTsO6@dAcrMjr5_%7rM(OrBynAOte>I>Qaj!Iu==@Ng5>3q{ zNiHhDr;@0vG7XOyBDi!ujDhN?BJ8yw)uVUcuq2=EUEoIVYc$I{80ELydoTOr?o&u!xlxl_cxWW|mFckZmgLjQi zXZwlV2)|XOjmzCaOb2o;nmO%g<$A;%Y-;j#h_|&3RQYOTdqKVyklqKsPhgJd@W*=J z;A^PlzEkYYX+RMKYT~gPE=k{K`RZx0a?B{oAptueN6)|C4#=6@IMkgCqe+*17{$h% z8zCGGO%ObYA(=Gu9n-pZi{b1&b9SpiVp9vy?kA|%PhvI(6cR~S{be!TY`sqTWe7ZR z+^V?u*l`kXg_vXqqGy^^!Ht9@TtB(_T-)+zk0{XFDS%_1wOwhioq=xlIS14 zD84UAy!cjYf z80oVQKQZ^)oR|V=V(99R+H=6q4~HXwrWW_x9b%lmFSd@24KXFWZE~BC#cWhc#*D{-8TQZZdtnDR3N^-zN*lux&_vm!8!h z%6BB@efsEkkLG)-liGx{Eu$kz^PwB?R!#)|vhR*QpAQf(_WSIB$YZofCwM6nPO4n5 zrUV8?!TtHbZ@|V^P+TjEcoT0~J)Re~M3h!K0z#^#IlkwdWv0Obd}iRq3j8_2Jh&=~ z78Q|GpsyW3Q7rZtWpAiguW)y)r)N$#QTS@UKn0HPburey6z|D{Nv`a@gwf0)kYs@J#SF5QI zwg?BPEYR(hNWz zFGfCbr<1swtuisGaZ);0Tq*48qJ&yU#KSC@oS?;YsU^fq{*&=W-ciW?_9LW|uZRHt zjt`i`!|%OGKfYi9Qwp3;$~OYTj`=gWmhnqRlSzNkx#Ov|#Ema(LO{q$<$HhIw~k2& znY#y@yQpH{*4BIfdkOi_HaEePgzsV95xFJ%VZ_g3E-rxhN%KY~?^y5S;Bo9&F5jdg zzS!L70Unc_ z_g#>;)n~QZyad_ha3lY`I|INtdX@6)jz9cde<5%&%aYHEMfHu1s4Ue&|G}Bo;3ET;JVZ{x-Ehs;$X@29dAdjdZ*Wm=b zjPb3~%LD#^m3!i*sAP^JG(Cq2T&QM2XvrmpM;RIgKMi4#Acrn!TUe4fb>9D7VlqrdE z_gY;pLZ~32#24`L6Z$nWdl|samVkr;#r}xA60YH1Ia`<7U`KwO2w-2^HE!^?D^s&|W z-m_K=hRELOVg=uiQ0qe6Gz zA0zSJBRM`lPVC>G`^ho%<7fE&Lhq4%T)axZud5%bhStKVG};|IPQOl+5j3m0C5rJ2v^O_aOV|1a9$8N z-)!jgC!LPpoD2Lo`8S)J$Y1Cjy|<&IJLQzLoB_lUCOoUiGi05_wR2*A#3z=mR2tdl^}5IwuaBBsf+FoibenHvac zS~cw_DY}Wm4ZU-mKWN92ibxJ_8&(5q@8MCY&sXMr_o1`AdRUYWm3pQ(Cn+B}$+ceh z$jo-wg>3Xdmzw0Q>9#>GQn9^tKzEEuI(!SKPmNr1+bec^>FO|6YB}%=Q{DM`=7fNJ zP?Qqu6&1Pe=AfR1O=drNXBW`@nNg(y+O{sp|Dzn7_%^obkIr%eJN;hUNc}azLJceM z$8yhf_N%b>A*AMLe12!1I1-CKtBdIKpFU53FPoE}Jf(;CGTup(w|eF(ebYMnJa(3J zZhIGCevStCI-Gwq8sO`2{xF(@;t+h% z?4Wr@dZySMU8ykDLti&2T<4Mc^nhM&O0R zAqRM)=*wBTRbUEqh@slh`QBVsDY?wsuvUD+4MO_aWxhGfll*hG<$JP)1b%0b*1s`G zWZ|1H9?jB6870m@02M`XIknxPah{&*L?BR0qqryNS1Y-r&t*0{YZ}_gj}Rt<(3;O~ z*02`)4b|dK;9vl4v!+CyX{>_!!n;pU-3}z@MM?$+T(x;R`1EMKT7xj?jVK-2XO2Ny ze{P&7dI?G#XfhEG$<)l26CzYm#$gH!wTp0GgY?Rs>_}JVluC$W&H6~LQZ+&^4-St~ z>P7J3a{#DRFB}INs3#GnG=biq?yR~e{(f%<9c)xNHB5DQN$gef1%uL16R#Cjd~n`m zWL+x*vB<2aTWpP5FqgM+y5ewlR+oW2>lrBA)W+S>OIGT^)r*ZsN|GgPIoIdPI{0~; z{S3gW*|q+oLGs_QqO|_M{SxOlR2Mz)nQl1nY4(lk;`+M^=r0M{ADu@ZqL9FMtg637 z9z*+Cey?l!D1TJW?`+BUJ|F#E5}GU$X+Y99`uy#E4ETCbq?12U7<|dy@YMGFMuU<4 zEJOu<*U$5_^yUYL21y+T(Y2&YP?_H=Hs2jd>YE3R`p4Gmy%az@>RNR>pw2Al&tV6$ zOJk^>UKhBp!k1X%RHC3kIPN7UZcn-&zv2N#6B24w2Q)8R%q^h3&~=Dg)^*|TK>C=b zZDHhPma4Te=?5k-a&Kls2i|JoR3M{a-HoP`|%eIu(WfKs?14V(t z?aU*#V)y}(4>m-ct>QVv0mI1Ow7!igwN5Vp~~TnN@lO#^rU?N1`l6w;GLrkTyB zd$Z4%?Vf5|eZs-9?9X7JqM99_wQsTQl>U#|jX;9-+R6eH0_aYbf^ZXU~ zWd}n4!V|H|Z)UPw*~Ib#c6}TZ_aDbTMgn{e<=>73_#DcgM)DUDXTK_(y|)rE5aG?k zH8Wwa3>%$t+YDhQap0s)2MfmXDb_?6sP~=2h1}DO8ST}R1-7t+8U@aeWUSHiCZYF% zwxH7(E9p6vRY-|OOtGyydW6U2gGiJf@g|wX_@oy~LwBw$udXW!*tly)=|no1a(h)a zxhrf0ce+IioeYl!g{Gm!wbRQ1FA|+ha0ExzqHSGPpd`uwa;CQZDY zXb~N2j?69qr%<-r=Su;%Uhbfh%G_#-IPrqy@`cXI(!h9NJZm8ZEB(^hJ$D2Sl#~gp zqQ$K9ND#&GtNRIwJnV6x3Q)-({pkpmqMeZTYRBf2;{!JOs3%TwFRDF9_eqg*I@|n( z=+16jfmhFaD(9C=$bIY=tWttnlU!dYQiHl?Jyhrph^#KiGHUw#Y=AEX8yDP9bTl?T81>gKHKJV~7fS@0Ro2uq{7P7n=hhErwt!@drZ3(@27Aw=3?;qOuCijkrFI z&eJCRdt$Nonaf^IAdZMHmcqR&y6v^G0RIR)Mdx{mT(7 zf03H_!e7MC4Hvx23B3IxBK*fD%wHpM-rKL*&}+VL2REiGUj~lAQmON+@>}4W{!(Vt z_OF!R#^*SOd*gM+Lt*OxGR2<87C`-`J)hv@fogUP!4vhp&4Y;~wFt|Xn$d*%TDPAb zxTH8B)C~CAyOg8MedtmL)#DNn$npDmc9}>17gU*V_HkLjM$NFe3W$}ZPOc#R7`wz{ z$5&CJUCW9aWlGdg=t3PWugKtciuYO4g@ti$K)K$#`I_p?zQaH=H?*X`Qprp0MUEf2 zaR-b2`HC2a442Tkxi%N)s1hlJcuz-FM5cQw7qA>z3N(hX=hDXE| zw&y2k`Y39lBYSx*#ja>mnHc7!+hy_f;)%O;yJkYtcIOO04ks4kG^oEGS5~(@B;n4t zHPIY9U6)Iai9{y0=>=n9 z=PQk0N#v@DlEK{%XLTR!Q-Y2i{7QTyP45lIXJUOIU##CxkYU}nEgA)u=NXuP&yRD4LC-0ug;BXu{90n8z`3p!}SPPB^ zlH)Ee^ju^Unb%XND3rpneYRbWh|BT<31HabKthURmoHwT*-=&cDjy<3IxwQl$gM~$ zHg!y=`eLzEStv{Ls6CYx^%Oa2Z8rk_nP@_9wF*|dHqWh$tYa~&J?ANQJIxI_z@xo3U^tzea4iii~9#;+hS4z&#^vTFAQmnjq+WB8yN>;$k@Qd%~J-8nyqi%$Inl z6XqWkV$TBwpOi(F)&1`NMX4|G8Rr1s1D(Gw_5Ha8B9g|Xb>Qb5y!Glo)l#23R(@8a zvc;DZ7-KZxwsj$7{>p9e(T%55@w)>D_$6JScotImXS@__>Glpm{0(Wsp8*mi>dsqB zY&pK6j{pfcuC$3e_T%8!=lds*2mIah{gcN7{_gqy$>Rax|D#>=2Wly~zUH8m_hH9C ze4Hrr`~r&bRz2s;Z7pf(-6K%SB`mfe%kL;zmC=+!AVVp6Z?-KuB({c3A$?3UI6r>h z!7%^=zxL1<+Qbc52rIO8ti?h?lp^~4s*IL7bD|puL`tQb=^OnS5~EVr#VOTGEVQqO z-{r6)HYQocimuJ!Ell1W^b|~L<;vcI>L#Az(?T1Kfbm$n)|Yx*O=FSmXbCwGIpC9Y zZHkqyMFYq4yz5$~Cn%=z5gVOWgSi!Fr57(YeLAjo1dFEbXU}-s=IX+(VL$o=uoioX zE3Au}M*yQq2>9x`CnuYC)a(p}Rl%QoO`hFkLi4PMNx^_h(<1P}TXV-K+X~4ES-dqEyu;SK)_-Od`ZQQ3n3@ z)B4em0$f}DR_p`(sOb6m5~@F{eNH(4?X_PK68N_esjf}ZQyA6dCAU1t{1&l$S*91$ zL)fQ3m4b2ytXyKYn=E&xl}YM2+aQV*uPa)2jZmv>IxX_O^XeyPI<6frBrfo-j)#!AXC$XF*7trE#a2DC_KDeZ3Yb>q$YzRDt z@^QoA>x9@*I-HcvGL{xmZj68A9$))!(}?1^W$G)3Y;DWs#joOfz+Xb)zktnONZd62dYZNtf#JHO7n>2;m-E) z=-z_~qpfictqLU0TbWOM#(B zc`*U9x7?MS7mEqRuO)B5PlV0slKWzg#E`a7kCQN61LtK zVXBV|g9$af$bJ@>fEORgV4h8j^cv&EHLQ zndT#P^3gr01OL-^;O4(biUr7*-2guNIL$t&Jx0Rji=5brWG6UFR!LD>B_ir!u3DA< zEpsioX=fc@s@pvhVN@VgWM&w5N(f*o7?Eu7!`uhfLEigbY>6!OC~Nh-@1@IRQ#2-y z1~#26DA#S};#wH5Jk*Xw5z|zGXEYM-12rgus3`B~7tC5#yQNpfiQJf>3}v1)sDJJY zr)W7^zi$_&5HjM;G0>Q1JfINb zRftga`K>j^8Hs`R-kOBTs@JV1m;*({d%aZaVUY_Odr7E6B6J@hu)bgLMV?fyd(`6V zc~Yy`e(n;z1L4ICxL(CCY!*O|(pN1Im)9+OgzXfdO(fA2f@l}w4dJc$ekYGP=*kX$ z$&t~OLlpsRJU*1LP1xPyiTk5OBv8-psgdw-G|t6NM8_;q^rW1ablH)}>NsJkm26&x zm=G=wAdC0S_ZDY2<#yr}IqtKYd3Qyr1!Y26h;A?6OyY6(O~r+zB2$r|!edPv-k#HS z;Q(B#sgkLq1`W@|+`Sd+HiP+vU)3RjA z+lIhHcEzRc6O_bt{-NnDEUGAsDkc6L9z>N4KH=fBYxFPnD1H?IZ;o^xGz%q-?&c*b z`J4nzV2Zw04w~w}oghEIHDu`GNtxwnM@n@zz0=+1C_6R#-G}m zgL?kb9#Ne+M~#v$`L&EFG^qvn)C+~=*Mg)kWj~*KqMTYt9{p7J%p`v&ll<#(jU=z% zUN1gnM8QfmUka1HR4VZ-`Dw~HIS#3k8F5&V6u%(fOVS60 zJm!RF@6)4VmPSpk;KnE$22XWU1v{_rjoM`o6ta<(V&Az^6F}5r_meT;8>HgKKqI5Gk-r2~uD{R2Z7wNb7ujyt$T5d6HN( z3|jo)M0SDR$XN5o)lA>+;uU*^rH*YICC1`LWH{&@28`W5^kl2#o*G2%!n%c|H~ab? zB;;|etNn$<@jA&&6NPP$p$!Apii&X!-3$!knKp2ZE{v0-nbe@#RnfJZ=2K7YW}goS zcSkmza5w3sY}SPk70LbRi}37L%S%o=1|(oLV5iQ0#g%b%4^l3!-K22MYqan8u!7zl zDFingMXE^!YqC_i(drkHW5$3cp>intnFFrLlHhL%$pwud!j;`vU&C(ov&3$1`1-J( zgODb!)0y41^pJ_TO6}bU)EEAuo$BeSK=|a=JkHSzt8U{GFdCcggE5xWIHp%C5d@BC z=R}QO)5{to`!3$QdU<7+IkXXwgL1&0tPH!suM~OgoOQGHcRk@rF-Y?M@L5Y3ygIns zTyxHguJQECG=#&D9Y&^g^-?|$z=Y_WJB|Ub=JolGs@d(8M-hsIBHwp$x3>_<20=s? z#wIm>?n_J|XDXX+Lg)~-Ndc9jmN+}zy=RnwZ`GX)Pxug{VHBoWHISaqhvo-@xh9EUDOD&p8dniJW>8>R%Ej zm985c2z_h~?Jw)ne+Xn$?D1KM(isu`DvS_{Fu}8yKHrY&p`_Bpt|di#mX5lbXCyJ`MTacpGs|!31-T=i3}D ztxW5FboIB;NfIg3O{4=`lDCa6gtpF3#`Kb(6H>L-Bg!LLAcSd_x>WMztBj3xLlug589v^E{J=}!pXdr^rB{$!|Bckz_TOBbXzl~ zVaI}wWi%OJr@j07U}F7ZN{VN8w!ALr(;khnQtEnhbmv*!G?fBVQnFZB3st6Iytg0@ z`^4i02uOqL-SO;RP+fnMd2u>PS0NflnQ##G?o^tH>1&yCE*;C!!siAbUsqFr6!;ymc_v9*x)kv0Z$T< z0!;3$r7@@+&|N(NVS+pQN|Vn%Ny#RYy^ssifhB__2BWDONMsiFkU&6C zi|YlRBj%RQlp8nqDEDt{T62HU2jrv=#~H-e?@MBNbkgU@rx>J}f$-x=_~@Isqna;r zPmxX44oy`RC#dWXcUXm0 zdwp6`?nehlvnl>0^0|BDn|V;wHxchz)oTt3dG^zid@_FcvyTOxC)+<3Iq^<$pA!aW z`Vjgb*K+e50l9uW(*c#H{OD_LQ7CRwJg-(0JzoE{#y#+7eM0CNn)vHpdbddu3{2rS zY=FIlU%9`^vVpJLXcXG#t8e#&S~3HzT{r z2*ZJBZQonj%@Nylsz}yp#rnE8fp=@2ul_0xnYgWiq|fn!EyMj?I2Y2CRou_E&_31| zAZatiJ^YyoN?hp-a`8$5bCn&3Z?jO5W&0ej(9hc=jZ*aIM_Are7P9T3lN5HJ}uFtdUro zLhTSrnQ4t0);%OMz@w9jMug2@13l1IoO!HN!oL^Yh<8$XX9hweqZ9*f<e9`-e8&L}eZ;LDDQ;^*+fZ3^B!x~;yZ93_^ z!rmfyr_0Po>QiFL3zzdip_R^%gf9~+cLbacNl&c|w(IFdfLYXYbTJMuPMI#Ps=4fVkgEy29f&u@TgV77APOG-hq+h@ASSZ~r z(k^^)LA1mt0OUSumLP)CAe-*cSNdKAG43C6Xt#F)t{Luu5OcPRrA$6%uH1&8M+0uW z50@r$q&MKn&mx-ooapw03%R0Rt0 z&e7RPes2v5cf1|RRuWQBwX zEda~4%ZZJR;}`Ipwr4_uhR@91ZETwYs#d`Jo+QbBkw(O*uQ`@Jv{W*0@Hp>XFb!H1;5nv}^ zALff{s2}N=^eLo#>djzY(YG3i>CA&d=tcN)NLtVA+1 znJZ~@NGjEO&XeeI4{Zidk#+P(JF@T*0AZxx!m6LR zDM$yDc-1Bzz@1C)kCcZ%0yFvaNW>lv?+@PWmu1~eXl*hi)n)CuVSrylp@zxVP35QI zVquc>-br)b26*@HD7l01O0))_8_<-%Y$lPQY6gm=YX_3D>p<~J^x7BN&s^5x|YzjGO z3K7X4?+5<;fwstFyUt_wzXBNGcZB)700aDvFnW0{hsO}avA3G5Yq zMykKo;xo+eHCMr^G35SP_5!}Fd(p2|CVwru68IlQS6_uYuJw7%+;ql*_RGrkx4iaW zbQgb|=t+CnMRL&7VH1~%AgoYI@#MYn+3Ev^1VTO%rO})*vxkT{d2)qa zHLj(LKgP}IpFFHYYYjEIaD6LA6j-?m<|bq5y-3g;fCbpC?@{7eXuEpx-`O*)gtdY$ zId_rN`=D^9be+W^4i#Q^?>=5_U|Pqn<@fwspI{(wqVA1T_lQytqKDQyfA4hLtmK{{ zYPyE+y^(41gC{Q4QjtVycl!)oJQoxZq-`Pr;9erG;!`B%)ioc6w=$o(+hD_1q;fjZ zJ(b!cb#QoQV1C01VU(sE?iq&D-`k@bGz92v>IPbvO!*?!mjxV1sm=H(=r{?(grawb zOR@?A!mkbCP&?(aas(4)|*959+)bT-Z*&{C*?Vo9L-NXd8a$+M!wX?#|V4eMCf?R z2PMj7*Pb_%c8S~t(rAhp59bY3^>pT_H)7nijx!;4Hppo;8_Q6nk;~{tBvK~PokkhE z^Px@X?Y;2bz?l9~HZ9DgKvtB&7`NIRo|Bn-!y{9tYqYXU+BP$ zoiw>=Fj@&axn)cUBp*U(UyKdZO5LpSTu=JPQYcN?fKjZKW`2=X*tUPEpLBhk1Eoi8uxsBwVWxqRB|g80f%*yW$KTt+Ic{DmFlv{Rv{9Nrsbp~ zAm`7RMDpV$^R&6XjucMcHI>=151P2{X9B?=IxIWmLx*?-5RJ}3C`Z_W}FrVF#tF}MuzH_Bc$BQwFVz+VQ+}S!lbt? zcdN#XvdF<4Wc&FgOeW&k#74ZJ7xB`2mXHcy4f&gW;#LLmstp}+WGNR{vY(=;g-;N^ zzcOXJB-g8*XpDb`uHgP6jMRm_rt6vUl>-MoDfM0(KV)8V?)~Wj3#)(GQ>p&EnFmmm zjnU8dQQ3zF0@bll^5B&0hH&2akn;K3YIsE3j zYI*LLCAx3It&U#9#YyaXAf(CH6Y(06*WhO-HF0O=Cv7~D$2*=oRh(e+MJMJjsL}Fy zAMo{!^~QeDcmAB+b!hh^i2a1rLqxTMjaBML|DbKUALjSR$$-G79HnMw)qbv$`MnDd z`&LD@{zMbMlxF>wdzLgnn~ZcMMh`!r>i8Sf@H;aE{#R=FJEZ+V4Mkeau1s2&RY-*v zf5E87J7bsY_R^wDe`ktKl7zZL*ytVaO$dB+i`aQcjLeT+_)J)Rx_px@cGIUYQv>*( ztO1^J9TtJOm6FnR>{;e6KA0}GtjFsB9x&)De5tH%YP8Zwtoor4iBH!r6NX|G(YbI} zy-84_*Q4h(3twN<@VJagcrpg-vH{s9Z*ywZ8It+pK0q_mB(0toJ;)P=D@KXbuLDwy zE(c4;<#J=1Ypbx?BX|0cRJ;R-5H%+%j-#1cCj<&K1u8NKYB1joWZ3yawlMtcUFl50 zt8EM_50jlo^`NS(mWh2&fS@>#;c+B=#ir9B2-(YR!MF9E&LgTOEcKD@VM!2FmUR;} z2MzNe5$DyfA+o!SngI5@iTbf-Zr~Nd@M10p>rv=)Z4k`-e!m4DFjQ{n|1#uuPMN^hC{JFm0vuK_I%bm6x#*EQDy_Orcn9HTZoiuhSXnHL*eH*91XZmg7tLi=Si$LeuYg((& z0V({Aho2U#_1IL+*&b4%?43hpMA(T@<)5|UkbF+RDS%~`vzc{uMh3{Nr!^Ck0aF*x9m^5eou#Pv?{(@&=awW zn0Gh6B7^T4C&0SNVtvVJ>#qxAKfIy7G~0ahtto_fr`Qi@rS`ARE5JAP`sNp(nqQS& zu`lJI&Yv8gkIx_Q!@??1e@)B3I9UDA782Ptp+1H&F@hDUrLOF^bRA&V-Z_VU;*M4a z{?@40Yvq3^7;!=jSsyZoeI<53+N-xuImdTNx|fCA^KbL;msUKX{b!dd^;=!(?|JTD z*Oe;77UXAo+0+oREfOyq*PLwv+?E-D#bZunRZ2&l4SRV~w`XtSb!H)N8bYpgupJ^b znl4B|x0x_{LxJm6oYR5#!U27e0&qE_c@mJA`&b&#@sWhZ`zjC}ObIS;Q)j@p43>rW z&InXlZ$ZeB4;dfz7bTfDt6O(~$y72dPh#dbllEFIUdf!X*z$>~aPoEN5CQWPfy%}_ zC7D{>!5cZaxNQe*V@al00DNsz6}|T+7F1V!#q;o`%TM?DPMbs+qO_|>S%2QPQeoG*a@VmA8P2nO3&vw<5EaL*J;8G01MP z9qt*q(SfpG>q>$D#nt&&F&gF_73R|n_Y%2XB7$vi#5khvqjRpI#1dHTJp9M%3_vdGLz|1! zWHAsTF#;uMR815dm2F~-Q%&8c1h!aIi|pzeiK z-rfCrp^*H6?6RrTFkU5`d-uEQaTs!1!8dv~ zUa>9IyVU4ivcwe`P<&oG^l@HON=&9d)~dv?SENT~s12-U@7^MS&Jw#c#}zLQ_@ChF z^@FRU{~vL+`oF?e$swyBxGHcO6nsdJ?~Nf%xuLJU;`WQVP#-?jA7)#hJnws6D0_c= z=HqetR~A?QHO>OR1MMF;d;hO+7Wf@#|Ae!)yNc^~oZUX6-=8JWCg#oDgphTxov!(C@el{3qc3Pq+(w1>Wnln#P@YUG5)sK_4STB!n^aEni85 z^ZAn@O;aWtjyspGaeeu1e0{y5i>2m3r&v;Qh`qNU*iAeVaq0IfofHjtL;ROB#zl*j z_VFyZ#Y>E7c-(!dw4l3<|R-2(afZF`5+ zhK}``waQ-`Wb(oibtecA!q}B2Q>3`gY)MqdrrUi5*Q_?!UkdvFcPB()Rn-FQ5Qn;K z0{nU*^6T})2MQj$KW&Zu0lcK;XRpRtwWX2jTU&s1;dE}2`|e|AUo`@k53{3Ra^(V} z;G%cOdUvUvm9L<6(_n<2!4&syZucT}Q%X6!jvLxO=Sp%Jsl=GheQiXJ!;CUt0kldk z;_xD0D|U02X_$|Ng|3a|jEG6_Pl12tcdL7824IQp2#JWGg-QDC4|`=IKe_pPVG zC*ojQXQfgkz+vvr*-?9Md$_sctQUR<{S(~1eY%sT^grTm%lv`u}z2x*wI4;V8-E$U!dO#m@BXf>xbPdpe zsF6S}<43cSxgsw9%3Rd!~4%MxdCm9$#Y7PFe)GZ@oX1Gm=owa9qX~ z-QKtm26I$RK_fPTx7?eTq^&M$M1^3wE0U%ZpW{~)BmDxF0cRwb+F3ep3dpBA*|%;Y zhHB^*M!>8rrUUiv_@+4I>PJ}<#I8Nn#HL~>65sZ7mI8%UNEsjMucM#d@nhC#9A``& zRS81CZ`@GXkFdSt6y$om+J|dFpfpoAOc96U^ETB0-g4BScCM#^f^vVBV;QR*+_;f+ zxi95w**N!^xKz%eF6}w3lCAD<4Oagn5$2>VBQ@|1kjZnEk5YUM#bo!#&W1em?;5PM zcf=-0m*`uYg}W*O@ro6DhOk%e5@;_$L#T;TLL$FDpHXxIQ2dIEk~WN!!ZHUaLgQ*D z!rpnyrAT+}K>J%?{$t7bDOL<)f;*LNcH59c=xRJR^g(NRF~^wn%woE(>{2)$Gv)rx2s?z zYn<*>od6}v7?~R+m+dB?&)Y>L79M=Tp7XA040>8tb%QQ3e3R|y_V&3_JCg^+9uQUx z>-|A@0Q5$#@`J+g>WG5f&n|v>RrPHJuf9AXa30>obXU3_k&A_VO&#Mxt#=h7(Ksl( zp*3K%OZ=Yzvh#WPD*H!+RdRjuCwJ(_$NHD8q89U8gVh%gzHeH0pFVdQ;@U5})81D@ z*q{9O7={X|@ayKs7wf%`3k(w@@Mi_EihOSTij(a6X`a#@7W!zvYhToTJ{|ZUnEY|< z%Sirgr}#HV0(>9JpGNX`1Qm&5GQ#yaysQUIm5L&){El8Vj;bw5Q6@>U9RC>g>wDjf ztv;D8m*MO?iJ4h80Aa&0Nqrz+GIe zQqY#fP>q}SJs5yEg1Eaec=R2Nu#7T$alBc$Tlv=>2O0G;>tNV`YQ84Ht9*hkcx$*@ zs*&6#xQRiYlbDKw)V^bfOXqHR z<@*8g(gW&V8MfRMHI=k8D!^_;G9x@OO9;czdI?yk%+AnVE)x*mZGCt3{lSl3Y0CFt z+4TG19`8X~p!Hq4x`F6mK3l31hgI3Da46n=C{|HOs~92&H0EGi!+2v21 zLu{B*-0DO$U*!|HHVCdBBq^T{k#;Vo8zX1xbn##@t}WB;KnrPX@2 zr2r;tZ#+3;Y3-V&52zrM2O@xi-g7}Y^=rB{@wJb(FSjE8?hjt=yBl?MKnVjqa z{Mh(A1Lw;@n9#JgrpKoob55zOtsb7o1qe-Gx6BneRBu0$_~%4{3CwEknHF~mf1=(M zAtag7mTRmT+@39}$_)s_{TtAtwu_BnN3^zh37Cq#rVVMjg2V0#^p8O64|4{wd5lGf zzg2~Rr#5a6hwc<}=UAlcwad7?QxIg0xOOrfm>6+(IXBW=3^A{4e#5k@Q+TWL%9z!H zr>i={5@DVph_l_JXQ9pzH)`ZUuP^KVm;p0@HUxY^cvBa!$>A_!qao92dx|VKcVuii z&0CWvue@JrZ>;g%!pQ4I3^VQ_q+SRp`RfvEl|`hkH1XR>7l)j45h3xBt1pGo)xX-L z%s?$vg6omia~0>Am~zeb@?H}<1FvQ#hONSCj?tc6hf2sv67OkF9X$crTM|<>9u6LH z3ArU7c#xKim}9f;Rb_$|qIY1srb{T7&h--ZIV$D%`s7tQ9Fd&O2~>d8`St|g(XGJ1(d)Y;H> zID)%C;4emfUqvYQade8o)IpqZjoQknnv?E(Q%A|92}nGV$f80ua2D8f?MyQd*6uYc z%+2AYS1QSpQC;Y=Fc*cOn+x=|f?FACd-Q&#*bo9>Rizg9^suZ{cdZf89P*_NN_SD` zq&UUjjYl1%TG~5eRVP}O5z%g7cag#RK4^mtjCZ4mq+J4q7wJtm$P2v@y!G|T_Lb}U zdEBP*prfe0&F|o)sS_FEs+#u;2=PvsVt}BUn@o7w!l^cg?V-0fZGy0cYCdPlZ4=&5 z=KDTvmEz;NnMldySd?BisQ{XkYjOi_kbcol07i`F==WoXxNMeLw0)qU8Ikoe8`YDV z>$$Bkt0&lUBj26Q7UOv7E?G45fCuV0{PNJ`)-!lrT!^UzMFdJ0f<Og&>#UGNOGN_4}BeRD+ zP4WlV2w1U+Lzbap1kiBD`i^uRZ(AOD0d|Q^KHU#LWa4mftEr#}u(xGH9txTeV&xfcX3U0<{AfyH=jsUlmP$-At0M=Pw(m z;#9YU>ks`I)7Ue>TG3YhH{wvhACf4)Cfp49!@TbBAjk}A6vyP_JyZLlmWDV&P2`3f z0>~nay_deQe9&0CL}d~cuGx|ydt(W@LVgYbddS1WP42evyg z!eW_;f+<9q*aCa2Ej3>>Aa3mxvf!k^(wA#Ah5dNDIljbGLy}Vx7NV?XT4U`DiRy^O82^O6P(2iLploosXlsTF$Ra%)oz)Y=6j6oslj1CBA+F8}L1{iLA$%$Ct9z zO=ZYUt?EttR8>{hr)(Aa#NAKX>i1(R`_*X)_;tnC{MrifMTdC$_1nJbb$!z{ewcpv zwdTtcB>0OpgdjDs-@vg=aVDg$$(JIs=NV@!-7rOp%H1J1O;XIYk|a${<Cv{vK&v;kxxZ3z)x(~3_`Dk2}x@rfiU{d)owYyFL;|Psd zot69?Rx<<5%C%x0Vu2XkdO4i8N0^&9ML{=@O4W|tLi?$a_qO_I^!z4uXGg={;48(# znjKmy$uQA^k#KbL4d$y=`k$m|N%Y$Zes!^ysXYI7?I&!mT1PTeO;+TC&UB&VsA#yK z6EqOQiUy10T8Ki0fAFy9B~(C7m!7*q62!>2&d;#F4Df9BW7%%2UFxBmT( zXDHSo|FUFU_^q#{p;X{EJ1;M88~n^Cmy@hE0aDB{vMu2kh+sW z+?NXQ@5cbYqQKuOzD@$CW__UFqu35225F5p9P z^ydHyL=HU{A2QEx0m!E@UJG{OU?`h8#(ETO7bU2m?v?CH53GkB#S=r*iaN~xH9c(Cb#TyWH!Zo%O&D-Ac=X(CIZkk=(>|9 zQtw#0F`fM;=B&-fj;!2%bZHN}bgz!{MgAmV)8W9`h+^$jqjyiZI{W&M67=q~s)*YE z$;zer4Q_b1`pNqCBR%;I4Nv%l`{%(vRO$z`=wCK|OA=BK71Ny@`&idY6b=NGAMv_5bbf7F`MqNW_@!k`_%NT(Ado+slMYrt z^+CF7Z>GdF;J%|T;mTy5P3X60vc+q&EA!P;`^>z1#TD}DyVKm__T?ZJ!g2B?H2aQt zKkY;;7(WFD1MA-*hCeE|0SCLY9q-z_pNJ0%+I81fgoD-IESY;0)H;P^11|a=Go1s;P)(;81y{x%>L!c9^;^P140#{8FEe>t5{Oo*3_@Di(mSlJ3y8ON z!VKIV_KY!6XSGWNB=u?KRSWpoxL!@+nVd!`%`V$aJootFUjwK#h; zfZRcf#EgK@RTC8ygcRuUu5vhYa-rj}dMoxFjOt>y2rBBlips5O$p?>AAxgr`aG*YSHxrx79bXb|I1Ig!b(jUZ4z^zi z=qp773WgSMTcpnjMI=Zlc%n$MJ~gT%|I(>ti2K}uXA~teI%DPws0IQBK&9;|u!cvG zvNCAMRZU6D&|1PAo?}<2m7pq<+(@&_;$HMOtlj!>_WcW$Ac)yO1c2p~m^WxnY&?A( zhoA$4tF;Fyeyy&-Q=>vIr_HR3P)#_~wTf`75+Q;v``)nv_y-mKU76>f!i@%0N?0JZ zjY5`1tT&8!)YW>7{d;7{#}D^jhSXJZ<>~TGr8(!Hs6~EJyZh_K;q#%QO)wxsP)P5% zF)i<5+arZ!6+-o4#H}}igQ+U0Rc9ea;I*9jYaWYwc-j1SmxxX7y~V*9(_p6qk%_hE zg;q0kj$dRPcm9PF_eW%1dWLuBTc`rMaDS=HMz@B(z3z-)*^GkZ}MewgyzyiXuFYtK4V@e-AY@$h2eg+4sd;^Nzp zXyOc|lK$R$B4Bs`V=YsG9rj%toa%7F62{y)bz|H4o0C=7<^uZMB0rq8LhhS@=^Y~L zJj(8%;8>Rb2Kt0eIuEXJ+G(}IDGMBm{mf(A%koIBYj)mF<;y0c*XTyFVHPBa&d8G| z@u3UzDU5++R22P071E$9X6C23X08ZMLl7IyTyoysH3Wl+sN9PT8Tix39;lKM(!;$btWL=-)>U{4Ya4X>R!^<@j&1CDd2h680lo z@&P|yeoqh9c`o8>kjbl=>@zgI^7*d95-HUw2>5N=>Q@orpyPGDl{e)Y7bY7*p(&eg zUP2eVRM(UdN-r>V$5^_a7&cPi;hR|FLr#t^0$a%t>$ zW`61<;TSpWlj_i&P$;Dat3<70cM;(*3i*Bo!k?LxA<1xuic|OAW%X=-ee#) zp1594Zg7`_w1dHT$LJ{qT`YUx^c^7Y2`eoVhCN3p;7BvwmN+63;SCe_NbTp&Wf@k- zhW0U~QdH4z&>`>e{zPv#U3Iq_5E`6(Ek2XwhrhozuNrRoQr7~5tF`&)10itUKBb7~ z(=^>MBW=ih`=fhO{eR5;$JV3B)-{awxfL2XfkYGUy;l!!1QJ%5tN+oHnN?Z2v-Z2| zt8vCSjm$?v0Yn7BTqf3<>-yy@I2Xl^b1<($gi^kJy^>`OC%w4QJK=Pr~0`PL`&^Ha)II~$0v zzw(}*$Fo;{9uH0t_bHnUe`rmC^s9=o_2D^v{LF)D{b&8;=BqICdVW6__K7wn#Y+?r zS?o-SuTRpXhFZ`{#=1mA}ohc3zo1K0`Vm6ZW}K z^fk%l=g#nF2q*ZzDdt9H>-oEwQh-|0>!%!cY*EW+va;`w@%}aYx6kCRXU{&U{g?bz zA^7%Q0OyPGmAv~YK(BTg8aa5I?qrjmC;c^ceL`TEbwshe-xm_*m?kwJ;11-Jd($Mr z|52}_jNrA52I}ul__Tio`y>7i^}z42{+~cS@H?#kCr}T3!+L?C*_p?K-&SG%=I&tZ z%6$jO&Pj|i>S-2Ze3Fh&pk=`}mIG<^U5XRBnyYV-x%<{2ZVE9)GFsTk_F&@?VKOuJ zf(3=QZORVj(SVYu&OmZIUM0!}c7HB8Zzh|*cNhmklkIrCLeXrPKISolwPD!Q-xKG0 zt$nFn`7Vf8gmz1SlnG3iZi+mjVQAX8@p!F5y3a1bMD=KG?LO8iih#M=TxzK`Cr7dG z+#B)q3yXpw4`fT~-k&~rFDCkl8)7YExZP$qH(=hKsJRkhm5)dy;1g085wl0~{uaBH zBy5o!itfb3SA5qnJ|?O*H1DE5q)d~PsoPJ_85HW~Iq7j)cA}z-Tzaz)fhVoZj<)Bu zcomxVuRO=c$8$XX5sJ@J!TKMGY~RU7^k38q8t_?O(zxgc_a$UGf9!*Zr-WD}A^Mbr z?IW~m)2?dc&^}VE{rGz4yF>Rt;?V86j>b%s7KyW~^M@rn*IA7Eue7GcB#aZk3_*be|$xMw$U`;ZyNnY z|N3w07jT+mvw6Y-1sRrcqiN>iP)EKFFB};c^vYN-7xQeldMV|6n#=ZWzBD)1<{;c1 z56WwR)?;uQt6RBCUTy2GIe1I96Cjr>4en?-aE8 zJ8(RC$dVUjsNI5r)fz?On=>mdD=(OJT(gqYI*w9JqBc3lyS6ac!L>4JW2ZQX5QqR8 zj3Frn1m8gZDv=MZKi!44-oGaMcI9U24(d3G9gg4~%d3 z9uwoOoK1f-PE-409z5AxiixSEw*)@H1;gZv=}rW8aFeFZ(HO)hl5O$QOaPi=e!A?S zzlsL!2L(3sWlf(;=)3-yI6sm?>#RC-W(4*8Y@awQ^^PNQ3E|;|P9ZA-=M?d~f;iV0!0OB9F_a=a1|qHo@=Cv@ zEpp=HU+&Q5ADr!s|I4jh{DQHbe{c@)gLCP`SlQ=z*@t;U^>q5DoJ^IavOmPN=6o@- zeM3Wr_W&P0W%!R;N&kJ9?#HIv7sa^7ru)a?3w+}mr@rsHd5Gb9_-S$ew!6RUE$~me z`@7x(f7jiAf^uu|R4zSbc=%A{j9c4I#ZwiL-GadK@~dZaItISUkXn$WuAC6oL&*er z)3S1&1E^GiMNQkR>MmBUR%fH6BrDX)K5bS}48HMl;e<4QR~%oJfwl2Zs}M_TlIU~> zMG;W2P%UI|nKL1ij;!g)jd|6mL({XhhRemQ-m+ghs){Jd7`FkDiqQEtstyJ%i#!DE zV!ivvG$!DwI>;>#RoDi~c~jFcCi1&^5u>(i*~^P}AzP+ViInzjGDdoYZr~L?EIel5ovRD#j-eEa|wY|g#t z)H1o$7ki7S>tG9)hxh~KzBcfG4_g1r2Ae$?{M0oWp$2dHv|k-ou$zWqgKqhbdcd!+ z_dz{V_c1dYi#i!Zma4qCrme?Ftd@)7a_6v24ZSRl2^A)10F4{v2Sg4y5mCjZWx6@C zao;r5+p(i%$U%#2ZR{Wv=@AzdB^$VeD6O$W%QVtiI{{&ySXWXX?)}AAB%dH8i5h9* z$pmd+&HBr;YtWYm$mRsXNiOBmwdr-Nup`AMkw96XttyfoJ*Af9?LN_7I%jdSsU z7fEs}y|sc3W^?1xAD9jajCT}QeS{ERXI|-Zk1Dt>k3HOq#~q03e7ZYo2p@-lN5t;k zHu)IW6?#sFhO^geCV3D0CXW9u5{Jz`sMmu3N1`X4{Q@J3$8s&8G1?DnCOw7PSH12( zLR-FTk?Bse?tYnE-sXPYzXv?j|B!Ni9$dp;0*0KH`b&DL$m_fXle)zJP!4$=|3m>Kp;lV(ZBe<+v;R`|b8^L2Z$Aul zpKyZjEXhdHwGHqi-ry_E@&lFsV_N&SEK14;3}4y2(I7UzV>TXf#-?ZQ5v^{J61?>Z zZOOR1OZzK)vkg-n7>1{$LtN1?U#r;@M&L+VFzZ1ObT6o`P}jAHHtvMz$AN^U7UK2& zso?QEAZi#}_tW6dlE8XBnKxuzxZc+Qp9(R3vH234ynB|UEQi_H^P&yMo8yxU;ScvX z!S1~`w8WA&W8C+dH&ZjyO$c8;ETGcqVQ*dn#bzQd;-PzhDuL#gS{eCwtNZ86z!gci zR`x^4nQIc+BT*H;@`%MJKL-ZzYMw=_R;##|Pz`NV*cq%TX@k(W<3Zy0xOv}_EeS;k zQ8;5Z$|@p8Ce=Jhm=VWWfq2!e)q!vPjBq-W#@VS8{#{fjPYwJKW-WcMZk8loSUjBo z!{n4Jd;Fa~_cvioe+o6=mo!Sv7<6t_TYgG&x0p(md8ozRc%|32ofvhHLv&P}KFIUe zP294c2hx|kvCZfl0{EO2u34by@w`nT^xC^)QXTZR>yRkksQpPNJbavj0=>J7oNN`E zn_&vP9%Ui8pz#3T8(0;~;awY=mVIOiA6PMgba>RFe---c9=d2rkojX_9tJuhSsHcK z4VWRcsb5Yx3JR#Kov54iKqX6}_|Yj}DD2qv>E;o`{ImtG+wE)P`d4|dao7PLEWZPY z_h86UZAls$3%v{c_z7L55%0VL()|}Rl&)I0i*8LZ>^S;vB+g~8WMx+g}S(^EQ zAqHHXX7Sd3AVA{yCJO9NAYUU1{PH3FxQ8cPd{PuY+1gJXK4Aj^zEJI{ebbnjUqX~T zYBkFr>D-xg54MjpsE_t@$$nUf1EdGeFICcgI5zy_9`JjFmLDRd6K7jE`@$jo_@&a~(oTPUH~>!2 zK1Ihli2=F%Nb~<*etFaWrlKgPG z28z7JMi7p391g+6$PAt``?kj)5%bmwqJt0dIy;g4bhr45h`d6AL6}dwSgLW#JtrV3 z52SUrGerAssBVmaPwe@n>9>GM=`pl%u!Fw~Ae(}v>9Qd{n!x6bsG|i+fE}}V)_DE zDG*hpI9RyLU0x6Uc%PyO$fPN>ox8^O0t3hsM*6P=frFol{WEO#^~Y_{NZl zCaaLHRpf2hasNi8`vmCE0eU@kg1kWVd><-aRZI=P>DOIN@6UyMdtOL4@NFMkOqU>q zm~N2fUYpu5D8~sUpuGlJ*SGq_9v7!%lDm!;hWEB*GQa$rAhEA_TjCFEUh>zM-NGt& zx&1z0K0bcQ;&S}c#%L(*J7I}Ndq|(0=&m{1Dt#vlX6c@eun&PrdwfWOQwFEi`nCev zp&`bpmTK$+)sH`wUTR(Q6V>34m;MB-FEjZ=NdK$O3w#;fKaiV!?AnLwt~tT_N0R+t zkNu_lUqSN!ru(1X1OKM`pWXxiByX(0C0y@x57mHLK?_z-(cggQE(Oz$^7<$*%p|2R zx`G}_ATAySVK(v-*P2C6C8Ac?OM}E_a(^(7o(d5ECMD7{1TOJ@lQd)lW%Q9sJ9;?zBdu*V zPg9vqX zWA&MB;=q-Q?)u_0JLR-s-< zZ(eLhtToTCJnmwlhK3Z}dY|uRDw=X-iaCpNL z1hX?9_FUM-gc|>aVqE^X0*$F`tB+8ln zuF>-V@}pW??ZHq@V*PD(?Dad>FaJCrXK_HlFd?1qS$JJXFQl`cLY8GIEQb$PI` z4cAu~XePZ;YrUI<989hW#T{)q3=%Bgb;O&A=QDe4!CaLzIP$WB8pR)PQ|SujQm z_5gxcTBQ-K?;v&Q4)6*t)as_70HdBI*p1z;%BEm46Dxc9_V5_3YAD8Q8aC1R-Clga z(O{cTo|NM6Fd;RV*~H6?s-)Pdc`BBc$W;kC?hixlpI6@l!?q}p)5LZq;Q>F$2I$w8 zVQlwCDNm+6ts8ZsDb(h#j?oj;#Ja>@(sEnDYf7K`73#JHj2Fo?T%ee_?0X1=@Tpnd zT>`521{I@t;n3aSzyz!iDH0#u9lkm`*qbcmgZzJk7TY3K6Ga1{CRAY(w#d z4*G3N)k`KzoN$S!o{?QkjVI`_p$D{h+C(8wEP|3Hu#$o4eU96OGx%;BP}I2 zPQd_AK(N0Ci%E5~d9lp5w7pTZMyWD5my0TzCgsVOcF8FTYwjI%)p0P?;wdKF_Y~4Q^z~c|kmL+W9Jl8BP>lzwEg?NkhGWflZ zpZ~QqsAx4@q|wn2Z0CX*bFhGU@2*4 zKV*cvg8*d=LhiiSw+mxk)OIr%DE=#UpF*X^l%qXxjWHY6(T`UhMUS-daIztT zcYcIuQCA{RyJE^d+lPoho!~lx1x7p8V2s_W_{ba*z1)d!&wjS`)zcJ;7Y z8Zbt;xBejqUJ+-VL9qedjv(hbVE+KKzAW0{DqwqWBSp@_GIx z?GWITYx8IhPaCMJ%6TKM@`HU%)&2O>cmh7w)AH^&IqXy)=2|I=)HGlAJ4L8c@ORau z&&Ms|5d^^qaHKVlpTFgT1d-2C>zXPKl|`}(Eeq*=YP04K*Sg`Lbi!^V3-S#D{v#6N&cRVYCpfc&=Iq<%5C0OyA z-Z`K^T;v5Z=1tsu>2>Spm(W}S#8Bylx`X>H$u}+PME`_D_Ud3X+QPl^@}N-&m($SV zf#yyZ7)TVP3N2!>M7RiA%Ei8L6h1k=`R4t(wI6*pUdOBPl(M6U+L|W9gAr22;&kAi z&*!4n!*-mdBjWy5rNZhHD;xajvsZsx;Fuj#SI-l_bjPn%6pxO7GP zp*Gy8F^?axQGa*Ow-RUf_j67@XeCLwo$?7#cJ*`71bojq9Hb3;5l*{>iX_-;L|{Tc5u#%?$jeHZxu8ll&Go zp%Ck$4Hrbi**)#lV0EMOGIo9}Ep~fo%B#FTfL_}T{as%0+FX+k-Aoz7rIuoQLmhuPdh%SJ|}Ck*IM_T<9V3 z1ua+CwYW474qqad#tg7i>@&x#I5@-rat#r)9i?gGV|%k@_%v4XYl`*fJ*Bc4=9v(@ zCP7(KP?l@2SzPl_qqsSJJ_&n{TtFFWydM_Uv9b2HKp9R6hCmHwglIt(C_P&}h(q zu`D4d&Rh;Cmt6dMv5*x2QDYc{HTG3ImBaBIey8$7d{xCu7?!>s2p31R#D%LUeQV^? zP=aoxIqFF-zVt^20>Y!}>zfj|_RE>NN4Q#pg}i%QdeqSJoO@7YMezB;P`%XQ=iU5J ztIVKb!!!0?I|c*p$CyFGklu7hEikD*rnqRY$z{9@C8soZaBGBl^i!|d<+*wc>B=eW zY8+h0?s*N;07~c!v`1?T1u7P`;XJ_PMBK(L$x!Oev`D?gRb>t7J887bmNDMsV%J5> zXx(vEi3Psb1!TCdq_FiLGq(eOSWVnTy>7$9;+K|3J5keKaLk#O6<>FazJ0F~Xq|dk zO#R#z_>abtL`ipNi z`}D-2e`FPY-p0YL zvD$H7;U%X)7OKHnHH$~DPBQ=-scwuVc)afya==Ad8yekBjO`YSojy(=*zHH1C$*+= zuOd=|pnmV!WU(-Y-UU4cdRu-!M#XKlT;f;4ou7DJ<1{qDL;)E(!gIGlo5_UDStQ3b zeIP`$0)>|5!k0-aEpV>X6;3kuhEm@0@=rybzloS%@jDgf=z6uBHocrCC7hyKcN(jr z{hUZJSkZTj3yRMJCfu?+jh*!%>lX_5Jq_{$`EJX!o|OjC zLVw`^`6+Uhk8kJfw*q=ZQKrQg-c62i=(W+S$)`>;K6>F1*kJL_LLNn&tS=&}OYeSB z@4zi%sNnuqwX9Cq%Z9n5|Ek~eMAnv}2HU!Yrj1pum7ePe#wLbbj0-}wON`@4#XdWr z*n{@=I8{W&qS5AG(Kzza$C8GZKlDxG_^rO_{=ev(lg7M$=vK||RK~vxD=Y0o`ldF1 zXu93=boRrPMs45J#_#kK&Bv2{{&?z*zwO@t(mUY4b??9R?w?eJMr-$;(ATuoN0eE> zQ~pqfpAR?Vg@iI7-&}k3y*y^DNwU4yx76R~MrzSSJ>Egcv(C04_frj(Cd#rM zCV{C^K2HEx$jghpz*?2V%%l(>MNw1vLAKJfI)tmM&yga8-GUqrb1%r7H7+P-EuF5A zYGmRNV8IWezHIEmCp#M6&Nr+Wdbswf&_{@RX)Qb)_{hl^3GR|MNCxt7j7-|ZfUQSu z3jo`35s`Ps>nq9HM&UtjGYQ#8=Q7OnT7SMzQ}8mquK18l2Do;dYfDWLQ_A*gsAW+A zk?m3CIR|{T?aF8jmlFdh`Nnmi{1z)a3J8Cyk@B`)d&6iC>~fDrbGeD{6AZ(2(}CxT zRhTkdFTo|gN>DXFHa!pJj6Xb8%nI5jhd?%1D;=shM5CG0*SAs`i~PPQBK_0=n7yb^ zt(4Vwo3zhfd>SorTYW2&{o~o3eZg}kTw>F(%KX&SPpp+(Xk}9JN(`O`ora6ogo^;a zK@JBsymoj&BC^0Vb7;)VX6cvXS#K&lQPfr9iPgQraNErF@nFCnty>ZhV-hw->A7lL zZa#yCAG&v5%h_|&;)BRb0yG3>Hc7mXePlN!oy538d7-0R#@r~DfV@DdZ?r{ed0G(ihnM)!lA5eI>mb#kGy@KQS zeYf;msWs(kAaK5*EHRkRLp8*9&-Kb$xQS;=MF@BW*GJ?XIqc*iUmh8#NxNfWNtZEZ zh}iIJZw{hUF&)0WwN+}UwYh~ApY!Yh$+ z0tA-3Jran9-LZkH` zFS-SK4wBtBiodEL6t-E?RuK>$?2S^0w|3(Ux7&%Hh^yjI6T@J(v`Q5P7pJ(>KKmzL zu5GYbhL;#3wD=j}N{qLFv?)HrNNIb+6MDI5m+^d8VaFxs@?u+Fb>Dq_B`DeltEZg+VV?@oK{WyST< zxKd2R=c)x!&C-s*^tvtd+}Mw_5V*IkK`s@pH!(K&cQfQ;_ey&FikZ>e>Y-XB)+NiN zeXnda}8X{N442x@bqaYRC_U(!U&A0k`?9C)<78 zHqoV$A3Sb6_vhU#Uz-iLJTx~tv_rx^oNmBRq;5i3*&5=*yBJC8CZ1QEe6P)mPCfltv*|OpY^R z(#yvyW)#s#{W5_Z)LmKTg*i#s9_x0yzIkQAwDn$?KA>ISWUR z5aoCZE^I#+)>aX^4QUzp3P8id3a`EKzJ^Pnz>o-lD5&71i$5Zkkm#krU62FaheSf}@0Ly=V60Ij7g_X)vOZ%&nN7;kQYLW(!&150^n z@R-3JQfN}WymaZUA=o!J!oKAf?op9f>ke35R)^1`e6`^;&u!0>9x=l1>`Xz9i?3&4 z_y|Ibs+<=^yp9PAqpmyDqb74k4rsc%l!f6$9v8Ksq-kf54uZzhs zae7|ILaD*xjq#n`#dlKnVzmZ%yL!@(9zud0aTD#h2;vwf*S@1}JF+3F$>1^ND>hT8 z1@Xcn`aw5CB|e}@!=9Dx04C(thbdPN^0YtDcjyfS6e}}j5p<~g`sK!(m&p4RtxduN zpEZL*no&^R`fI7v^`!%(^WnJdb>bndxMiyLev@Yituzu8g#c}rUBs0^g*$4f=*{y2c;ooOpcTwVl>|8Gf5f7-wv za;pF`8CIi}a8*{;gkt6E?NVOXWN-Ux--|YsSIKRL0uL%S4@7Z0nUL5KAITFDgS03AzTu3g*s2>IR{+0>8%@ms>xi@7S)8_xQ=sxO&8 zH7^%ZQ&2u~Lt2cNyN~Zkok(Clo-AAPV&{LUnJn1m)wSrdcg2fxJGq@QXZ&ke^=%8E zUI^84gubtDg~sN0g__}M|H%W=A`@#0N76j&_}~`9qMp2dxva)|zrP}fkdd9Q^oKX) zy}lh}*|2j(ml>(xDF9)VOBu^Xx;o*IcORqz-9fvROthEYuHMG;hZ{`l&9y{yOL2r; zUpe|lo{+Yz-Yo=_iaic(d=U^b4m%M)ca%v=*YirjRb5no#On^ArJ5Qt0hiY(=IU!%X#xNM0RR60 z03iS0IL9|V%Dlv_QjqrcdzM|WTV2}RbDfE zmD1F4ZMcb<)EN8cvX{#*M*+17c)d)^`Uc$cipvROn8KU=r?Qt~s0OfHk9%k`6?N?U z()b#3fYYUMtVQA9+4~jngDvU%(LXeGH_cLck~NJdbAs01bYi&=q>ios@Z2)Cs zn#zI+aVR;oS{X)sNI+iZv~@!+%yqdn(W}HCJ~-55s`Q#2I)EgM6U0cgqJhF9QTdRr zcJCfLKkDMMIGmCZxt*lNloP7`rQI23n{O?GJ*Ah&kroPwvby3{gkeh3J>;|Z$TkXa zELgBym?bBAh@IU-46C0;)wOmk?k&qR1yfldQlF+FVBiiW2F!E5A5SG{!=PW>{GqMF zYKGBNQT;I9?uM-(IPX$%S=IuPhOl$WYKGR0?G3;f7CSsN&N6dT<44L6Yl_73>qA_J zy!Wly!K>47y7P)s0+dk2Nf2~yxZBgO4vbiUtkaeJLAQ@faS>mPRxN>mylw`>Yg1&D zL1YiL`OvS2+m^mCBDdG0qk@`s6zL$e2M0V7$<}EOBxafw>>K;QDGfq6(uZt1Sw!`v zUdKH!^&~wWAR7;{d?JaDhAC(1rL}^?Qv7nY;#=^@`99&ZD3iG&2!_BZVyBgW`a?Qh7RU& zzAn)-T&hzj!KoKluK{)&Seggm0+rW=+;jwWcQ3hi!!XB$D=zf79q&!AnI00Cd-|^; zxz;c4>aId21$gX(`sIjObgpYjs<O?y??SX6Vp?8>f~8R!e?MBwcG|uC*)VY?`TQJ9AdMw4n>tlc$~f zy(;zQQ{-J*K?*kvY!BHL0&I16%|IC43D)0ls+5t^u*DlEyz&;oBTw&H%Q=^LR!nh> z85^h(J>wj^M}{oVITxTBLbTo|938a7*PldMjhIwwjuQSiB_TwM4V*fsFFoM)CfoCt7yP^2Z;txl>hcG! zTE4{MFVURMmDcvxGrC}6=lqV#gr$*RgRpqp{fW%IT<@n9@l}WRYm+Rrk9*+npFo5Z zo!j#t0;C7`(wOK+Vo712O6YHP)xH2I?Yy5XjBla1KVyna*^&HV`LaZPR6D=b7%5^8 z>HEf@_Q&6#Dow4Sj!&2^pt3C#Q5p&j54Th1<5zWmu@deD5?t})tDDLO6p z!22zY2Jkmzjgq9X(?#>uVa+aWp>x;wq_QRnH=S^u0(FqcdVB@m4&=*X@GuylRDXTM za+7Ge<}x_`CLTN_v}qe5HF$#CHP!7RV_dvDMvZ${ZxMyO{%rusb8c@WiVP#w z@s%T*n|nDe%ytrEUj2itG5Ro2rC-rb!2eTyURvFQ<~sP*4grT1Pq%_=_ftJXXy>kR zUkO*)iE^OEu0MqXY0OU?j4bt?`40FBI$E`#8*)E4WPT1#S|9%r^b7nM_4`I~jnapz z6=xU;Ul1`bSAIA_FGoSU*&?Fy_}Fd7@^Zfa^?lr2UJ!iXO|qiWN4SZ>uW6$xDHyr& zN;}!sRP9^^VQyx6d&zo)_FkGd;L4!2Qg1%p5XuHi061KzUr(5_S<;6u(oLBCrqi__|?*U4Oz?g4mLX{~vL#vM*^ zJLCJ(ZHwy_z49FH_Up)IBR*zsIuCbMVj2%?P<3=u-osolnf9Bt zWn1`u@&`TiQGUg;@;K7By^p6=N;Q#a-=H@j_>3HBM=#5sxlU7d>qzvW6_m90Yo{OI?VEASI)6!o=h>4-2{^*3`2{|l ze3;uDnpUSES8M7O?T^y>uqbNI7Vn>&cMAKSVDYKgzUwY`IiK?eeB<2bz7A^5w}W40 z+>_g89u)aQx7Ayhee$yE^Rn+DR%r)Y8)Nodz5OjkIMqRnY-k$5_<4&#d6CUE?#R-#CzjFZ) z=RH;`Pap?#B@I^Ob=xj(AdI5u+s31?!?F!kvhC?u8rfS=<#LXD9T)edTo#uw0qMx{ zLs5pTNTXzZy5o>}3hQ1kIdzRhw0u81xti)iEgp(L4o`LU$N*MsugC&ycg;fT*Kch(T??|91Tc_$2 z;rAL$@4?KdjJZ=cIY@`BqmR}%YupaWp+!Lnh&e=|>jO&!Ug!#PkqwA2X>9bN<#CUunRJVV>@F9 zFOt7P(=+t6anRqvti3xnfp4aF2ZoK$b|q<)wi>MR$-eJWcW)#;v?@O{L9Np%rGME2 z?6%~;A}#s6oZBC2I?F`n@w;44jr)}l)8+xq_Ev8FQJ!q$e$a0IZ~^?uadcYspM0wC zsP{wL29mG63hMYGnPsIfxG>zWqG_MZj8m)jR)f_L-K{=F)AnDF0l(|kKj{_lyKeoy zSO0|ZLpOG3A_*HLk#08$qlN;H3uN6Lg_wMU=t{o^gJL-w#sH713)kykEgKvjDR>c) zmi_?cUf4`ZgB=c6S!OvFb{nWNim@CA>knUMQK=|H?}7reBP!w1QZ!GVX71i>_0n7P z^{&6%z%dO+Y-~YdT)O84!>Pu%$C7<$w~(EhA{CJ~ush}}9SHc%M{=>Ls;CNY-)3`lLoZ>;J12jb#D>sow?IuS2h&35N+_n zIM<^GtEV?Cz6jESIoFT%*2kMGPy|=UPu%VSsCs6osNc$T2(Z_6o(_q>M;44P3F&VP z5@Io=UQY-~|6u%JDEsxXN`jBi0r)??XNme%7bWvez$E;L7igOY7sR3VnM+S{+cgvXAt&nS1o_mK%5pws!t^!B^FyS;7IXErQzTcMxhy{u20ic#9Yo}y>6cO zqO}Cp(Q6TeRp-K!Jq)}s$iuEoL=D?JMyE-3?EMvli|mgr-l)&p4317Q9uMKspsRbw zku8FR&}*+(4Pq_|a4_DWTka*2IX`m|8rro&NUMps$S$oU50{bkCfbRkosX+vd!B&V zPd>cHsfMnX{RWs)(8cSkV{^vs1ZF9w=+R#KD*XR=dyj2bm1SGB&aY4q9#O<2;k~J0 zBoH3q`TC2-G;7Ya<~nbmw{N?J(WH?=Ns`Kp=n)wa9T)Yezuk)?(O&pC8B1ir0_Xbn zi^?yGDoc}7G-wFiyJCgG!8#lQ-$&L=>bDrQRt>`k*nzkI3g??2X}|v_?V&$Pdx8Gn zOMAJbyB~7(=KcrL-txkKk@)Vaanau-zPkdS#y<`1KOGtHZ$ta{k^L_9f&a1K-o4!l z&RXXeh^jKHFTu(mB>r0NEtU6A`;qr8P?!0gDj2=C??)4!Ldiy3=D9}cE~90i(+js! zZ&?^YD#GvXJYChTLb@E3liXl46#`JlfWt{D4y*0SqA(ocHDd+obHeEPQ%=mP8Ac3Q zs-z6Rf=uU>OH_-aQzKXVw6{-WVLGbt*z%Z5CRUnJDghnR54RjU#MH4Rr+5x;Y_>{k z^UWB0X)uOf3p9dkNK=s70zOnpeb*848IH%y@Vvzf0gY~$cgy(DQEsX5 zf+{85zmCCD1neZ+$rX@t6O?2w!Ly+KqNT=26jnfgU6)9#_sG{i3}?8~{1BbyoHQP!K$>p+wa{v{{1#jB5#pbC3m`?+ z`r|A7YJm99`~6G8d*Rpn)6&Eh{z_TwkDBTqmGQNlNAuJQfaOr-ukOF|eVsMbcZy1U zj6Y5!gS7?a#RN=E@@45$w zhXlu$ZkmCQ&iI$IARoLBk--!jvhBX~Ys?3(q>u(^7~R9QlXr0mdjOre4OYX7eYDI0 zyUE0H(NVlXrWP9^HYbw2E6YxIclT6tWrS*aQK7KB@o9EEMhFMmQJzYPFRpd}epA=0 zQ~S%@!r}aVy1cnp#AEt> z&S;H|VfNMrtf-Ybo550P49QStEnXWLkDSH{qoC0c0J66(OD8aMcwC4U&Y7On-~)A( zLG>27Z0@tStkjOtyEL?0vMGWM{}&qIUX(1$AjD5k5BtY-n^UM+*k+XU^#@_A=6*`rZ9pez~88dl3g+9*N#~<3IH&geut?Kl1VV(NH50`uOrUPmgaoy!m}E z^30}6=ErH_YejnSk;;6_jb<6uw8Z-OEZRO3ulae=`bi#4I37{CpJ_Iei+np|3~fd~ zJNfK{BKc*sz;DClKlS)E=)^i-g<(}!UCkfNwny(|0aK^VS0d#ceP=cTZld+eac8}x z`@hV^-#fS6^|t;-$yPB!5f$e)Iw!5CQ`9@cuOkX~ju7glv{C(67}jmq&qvkH_un}S zZtFJ()a}rm>Wkko&-gDE$zOj?*5rKw(UzpO&Kp^aDKQ^k(`WeKcmC%t=JliDKF=-j zYsAIkr{?5!`!LIW`~7o=f#4J83gH$X(xY=+V)XO)?Jkl z#KH3l+eEqo)gF}%ud5lxwboGp$$0Gg^woFM1=nzxE;rUAI*sq@iSSa~=!w9a-}$p+ zpR_BeV41Wu_s%_3i$?HHVgSPi&-`{Ziwvd|bf!@+r6bnBlCc46_flk!BY)O}cO=rX zv^|Tc)d+!OEWTuALQk9L^>9!9pwKg=Dvbx4&l@%=XnIstS6IWVXXRs~3Z6wG*Ka#$ zsppVIgMby-K8DAd0`958T;#qj9?G~(!qqT_1@_5{3rQ~J+_3R+nuA88^ZHdBO!
%f#eI#g(pOV_l44o^EIgM$HYO+~Eotq~Du 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

EeBXTC4l{l$EAJ+iDtt(Dgm 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

  • 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 z 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
    sy%`XM?Qp1U6cD}Om{^@Wp|2*kpu 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

    q~dGfl{#<>ja{k;a*=>K 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