functio 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +9 -0
  4. data/COPYING +674 -0
  5. data/Gemfile +16 -0
  6. data/Gemfile.lock +79 -0
  7. data/README.md +109 -0
  8. data/Rakefile +47 -0
  9. data/bin/fn +28 -0
  10. data/features/expression_evaluation.feature +58 -0
  11. data/features/function_creation.feature +74 -0
  12. data/features/function_deletion.feature +37 -0
  13. data/features/function_list.feature +35 -0
  14. data/features/function_use.feature +56 -0
  15. data/features/help_option.feature +13 -0
  16. data/features/step_definitions/steps.rb +36 -0
  17. data/features/support/env.rb +41 -0
  18. data/features/support/functio_world.rb +45 -0
  19. data/features/version_option.feature +19 -0
  20. data/functio.gemspec +43 -0
  21. data/lib/functio.rb +24 -0
  22. data/lib/functio/data_storage.rb +90 -0
  23. data/lib/functio/errors.rb +47 -0
  24. data/lib/functio/expression.rb +61 -0
  25. data/lib/functio/formatted_num.rb +39 -0
  26. data/lib/functio/functio_cli.rb +111 -0
  27. data/lib/functio/function.rb +104 -0
  28. data/lib/functio/function_repository.rb +73 -0
  29. data/lib/functio/version.rb +23 -0
  30. data/test/doubles/expression_double.rb +33 -0
  31. data/test/doubles/function_double.rb +34 -0
  32. data/test/doubles/storage_double.rb +36 -0
  33. data/test/doubles/test_expression_double.rb +30 -0
  34. data/test/doubles/test_function_double.rb +30 -0
  35. data/test/doubles/test_storage_double.rb +30 -0
  36. data/test/expression_interface_test.rb +30 -0
  37. data/test/interface_test_helper.rb +25 -0
  38. data/test/license_test_helper.rb +49 -0
  39. data/test/storable_interface_test.rb +30 -0
  40. data/test/storage_interface_test.rb +30 -0
  41. data/test/test_data_storage.rb +127 -0
  42. data/test/test_expression.rb +89 -0
  43. data/test/test_formatted_num.rb +56 -0
  44. data/test/test_function.rb +142 -0
  45. data/test/test_function_repository.rb +97 -0
  46. data/test/test_helper.rb +22 -0
  47. data/test/test_licenses_compatibility.rb +29 -0
  48. metadata +140 -0
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'rake', '~> 11.1', '>= 11.1.1'
5
+ gem 'rdoc', '~> 4.1'
6
+ gem 'rubocop', '~> 0.38.0'
7
+ end
8
+
9
+ group :test do
10
+ gem 'cucumber', '~> 2.3'
11
+ gem 'aruba', '~> 0.14'
12
+ gem 'minitest', '~> 5.8', '>= 5.8.4'
13
+ gem 'papers', '~> 2.3'
14
+ end
15
+
16
+ gemspec
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ functio (0.1.0)
5
+ dentaku (~> 2.0, >= 2.0.7)
6
+ thor (~> 0.19)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ aruba (0.14.1)
12
+ childprocess (~> 0.5.6)
13
+ contracts (~> 0.9)
14
+ cucumber (>= 1.3.19)
15
+ ffi (~> 1.9.10)
16
+ rspec-expectations (>= 2.99)
17
+ thor (~> 0.19)
18
+ ast (2.2.0)
19
+ builder (3.2.2)
20
+ childprocess (0.5.9)
21
+ ffi (~> 1.0, >= 1.0.11)
22
+ contracts (0.14.0)
23
+ cucumber (2.3.3)
24
+ builder (>= 2.1.2)
25
+ cucumber-core (~> 1.4.0)
26
+ cucumber-wire (~> 0.0.1)
27
+ diff-lcs (>= 1.1.3)
28
+ gherkin (~> 3.2.0)
29
+ multi_json (>= 1.7.5, < 2.0)
30
+ multi_test (>= 0.1.2)
31
+ cucumber-core (1.4.0)
32
+ gherkin (~> 3.2.0)
33
+ cucumber-wire (0.0.1)
34
+ dentaku (2.0.8)
35
+ diff-lcs (1.2.5)
36
+ ffi (1.9.10)
37
+ gherkin (3.2.0)
38
+ json (1.8.3)
39
+ minitest (5.9.0)
40
+ multi_json (1.12.1)
41
+ multi_test (0.1.2)
42
+ papers (2.3.0)
43
+ parser (2.3.1.0)
44
+ ast (~> 2.2)
45
+ powerpack (0.1.1)
46
+ rainbow (2.1.0)
47
+ rake (11.1.2)
48
+ rdoc (4.2.2)
49
+ json (~> 1.4)
50
+ rspec-expectations (3.4.0)
51
+ diff-lcs (>= 1.2.0, < 2.0)
52
+ rspec-support (~> 3.4.0)
53
+ rspec-support (3.4.1)
54
+ rubocop (0.38.0)
55
+ parser (>= 2.3.0.6, < 3.0)
56
+ powerpack (~> 0.1)
57
+ rainbow (>= 1.99.1, < 3.0)
58
+ ruby-progressbar (~> 1.7)
59
+ unicode-display_width (~> 1.0, >= 1.0.1)
60
+ ruby-progressbar (1.8.1)
61
+ thor (0.19.1)
62
+ unicode-display_width (1.0.5)
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ aruba (~> 0.14)
69
+ bundler (~> 1.11)
70
+ cucumber (~> 2.3)
71
+ functio!
72
+ minitest (~> 5.8, >= 5.8.4)
73
+ papers (~> 2.3)
74
+ rake (~> 11.1, >= 11.1.1)
75
+ rdoc (~> 4.1)
76
+ rubocop (~> 0.38.0)
77
+
78
+ BUNDLED WITH
79
+ 1.12.4
@@ -0,0 +1,109 @@
1
+ # Functio - Turn your recurrent calculations into functions
2
+
3
+ Functio is a calculator that allows you to create and manage functions for your
4
+ recurrent calculations.
5
+
6
+ ## Installation
7
+
8
+ Functio is written in [Ruby](https://www.ruby-lang.org/) and is packaged with
9
+ [RubyGems](https://rubygems.org/). You need Ruby version 2.1.9 or later
10
+ installed in your system. The recommended way is using [RVM](http://rvm.io/) to
11
+ install and manage Ruby versions.
12
+
13
+ With Ruby installed, run the following command:
14
+
15
+ $ gem install functio
16
+
17
+ ## Usage
18
+
19
+ Functio provides a set of commands for function management and calculation. Run
20
+ `fn help` or just `fn` to get the list of all Functio commands:
21
+
22
+ $ fn help
23
+
24
+ The following example helps you to get started.
25
+
26
+ ### Example
27
+
28
+ Suppose you want to know the balance of your savings account for a given period
29
+ in the future. Given that your savings account pays a fixed interest rate per
30
+ month, you can calculate the balance using the compound interest formula:
31
+
32
+ principal * (1 + interest) ^ period
33
+
34
+ where:
35
+ principal is the principal sum
36
+ interest is the interest rate
37
+ period is the length of time
38
+
39
+ This formula is also useful to simulate your other investments. You can use
40
+ Functio to remember this formula for you. First, create a function using the
41
+ compound interest formula:
42
+
43
+ $ fn create compInterest 'principal * (1 + interest) ^ period'
44
+
45
+ The command `create` creates a new function receiving the new function name and
46
+ its definition. In the example above, `compInterest` is the function name and
47
+ `'principal * (1 + interest) ^ period'` is the function definition which is the
48
+ formula for compound interest.
49
+
50
+ The new `compInterest` function is now available for use. You can see your
51
+ created functions with the command `list`:
52
+
53
+ $ fn list
54
+ > compInterest <principal> <interest> <period>
55
+
56
+ It also shows the function parameters. In the example above, `<principal>`,
57
+ `<interest>`, and `<period>` are the `compInterest` parameters. Finally, to use
58
+ your new awesome function run the `use` command:
59
+
60
+ $ fn use compInterest 2500 0.02 6
61
+ > 2815.40604816
62
+
63
+ The command `use` receives the function name and the function parameters in the
64
+ order shown by the `list` command. In the example above, `2500` is the
65
+ `principal`, `0.02` is the `interest`, and `6` is the `period`. You calculated
66
+ the balance of your savings account after 6 months for the amount of 2500 with a
67
+ monthly interest rate of 2%.
68
+
69
+ If you don't want to use the `compInterest` function anymore and want to delete
70
+ it, run the `delete` command:
71
+
72
+ $ fn delete compInterest
73
+ > Deleted function 'compInterest'
74
+
75
+ ### Quick calculations
76
+
77
+ Functio also provides the command `eval` for expression evaluation. It can be
78
+ used as a calculator:
79
+
80
+ $ fn eval '(80 * 2 + (3 + 1) * 2) / 4'
81
+ > 42
82
+
83
+ ## Built-in operators and functions
84
+
85
+ Currently, Functio uses [Dentaku](https://github.com/rubysolo/dentaku) Ruby gem
86
+ for mathematical and logical evaluation and parsing, so Functio's built-in
87
+ operators and functions available are the same provided by Dentaku. See the
88
+ [Dentaku's built-in operators and
89
+ functions](https://github.com/rubysolo/dentaku#built-in-operators-and-functions)
90
+ list.
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and merge requests are welcome on GitLab at
95
+ https://gitlab.com/functio/functio.
96
+
97
+ ## Functio License
98
+
99
+ Copyright (C) 2016 Cassiano Rocha Kuplich
100
+
101
+ Functio is free software: you can redistribute it and/or modify
102
+ it under the terms of the GNU General Public License as published by
103
+ the Free Software Foundation, either version 3 of the License, or
104
+ (at your option) any later version.
105
+
106
+ Functio is distributed in the hope that it will be useful,
107
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
108
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109
+ [GNU General Public License](COPYING) for more details.
@@ -0,0 +1,47 @@
1
+ #--
2
+ # Copyright (C) 2016 Cassiano Rocha Kuplich
3
+ #
4
+ # This file is part of Functio.
5
+ #
6
+ # Functio is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Functio is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Functio. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'rake/clean'
21
+ require 'rake/testtask'
22
+
23
+ CLOBBER << 'config/' << 'doc/' << 'tmp/'
24
+
25
+ desc 'Run acceptance tests'
26
+ task :features do
27
+ sh 'cucumber'
28
+ end
29
+
30
+ Rake::TestTask.new(tests: :licenses) do |t|
31
+ t.description = 'Run unit tests'
32
+ t.libs << 'test'
33
+ t.test_files = FileList['test/**/test_*.rb']
34
+ t.verbose = false
35
+ t.warning = false
36
+ end
37
+
38
+ task :licenses do
39
+ sh 'rm -rf config/'
40
+ sh 'papers --generate'
41
+ end
42
+
43
+ desc 'Run all tests'
44
+ task all: [:tests, :features]
45
+
46
+ desc "Run 'all' task"
47
+ task default: :all
data/bin/fn ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright (C) 2016 Cassiano Rocha Kuplich
5
+ #
6
+ # This file is part of Functio.
7
+ #
8
+ # Functio is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Functio is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Functio. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+ require 'functio'
23
+
24
+ begin
25
+ Functio::FunctioCLI.start(ARGV)
26
+ rescue => ex
27
+ abort ex.message
28
+ end
@@ -0,0 +1,58 @@
1
+ Feature: Expression evaluation
2
+ In order to know the result of a calculation
3
+ As a User
4
+ I want to write a math expression and get its result
5
+
6
+ Scenario Outline: Valid math expressions
7
+ When I run `fn eval '<expression>'`
8
+ Then it should pass with "<result>"
9
+ Examples:
10
+ | expression | result |
11
+ | 1 + 1 | 2 |
12
+ | 1 + 2 * 3 | 7 |
13
+
14
+ Scenario Outline: Default result format
15
+ When I run `fn eval '<expression>'`
16
+ Then it should pass with exactly:
17
+ """
18
+ <result>
19
+ """
20
+ Examples:
21
+ | expression | result |
22
+ | 123 | 123 |
23
+ | 12345678901234567890 | 12345678901234567890 |
24
+ | 3.14 | 3.14 |
25
+ | 123456.78901234567890 | 123456.7890123456789 |
26
+
27
+ Scenario Outline: Invalid math expressions
28
+ When I run `fn eval '<expression>'`
29
+ Then it should fail with:
30
+ """
31
+ Error: invalid expression
32
+ """
33
+ Examples:
34
+ | expression |
35
+ | (1 + 2 |
36
+ | 2 * 3) |
37
+ | 2 $ 3 |
38
+ | 2 * |
39
+ | 1 2 3 |
40
+
41
+ Scenario: Expression with variable
42
+ When I run `fn eval 'var + 3'`
43
+ Then it should fail with:
44
+ """
45
+ Error: expression can't have variables
46
+ """
47
+
48
+ Scenario Outline: Division by zero
49
+ When I run `fn eval '<expression>'`
50
+ Then it should fail with:
51
+ """
52
+ Error: division by zero
53
+ """
54
+ Examples:
55
+ | expression |
56
+ | 1 / 0 |
57
+ | 2 / (1 - 1) |
58
+ | 3 * 2 / 0 |
@@ -0,0 +1,74 @@
1
+ Feature: Function creation
2
+ In order to do recurrent calculations
3
+ As a User
4
+ I want to create custom functions
5
+
6
+ Scenario: Valid function creation
7
+ Given I have no functions
8
+ When I successfully run `fn create fahr2celsius '(f - 32) * 5 / 9'`
9
+ Then the output should not contain anything
10
+ And the following function should be available:
11
+ | name | definition |
12
+ | fahr2celsius | (f - 32) * 5 / 9 |
13
+
14
+ Scenario: Function with the same name of another function
15
+ Given I have the function:
16
+ | name | definition |
17
+ | add | a + b |
18
+ When I run `fn create add 'x + y'`
19
+ Then it should fail with:
20
+ """
21
+ Error: a function 'add' already exists
22
+ """
23
+
24
+ Scenario Outline: Invalid function name
25
+ Given I have no functions
26
+ When I run `fn create '<name>' 'x + 1'`
27
+ Then it should fail with:
28
+ """
29
+ Invalid function: name must be alphanumeric and begin with a letter
30
+ """
31
+ Examples:
32
+ | name |
33
+ | 1plus |
34
+ | x plus one |
35
+ | x+one |
36
+ | plusone! |
37
+
38
+ Scenario: Function name is too long
39
+ Given I have no functions
40
+ When I run `fn create abcdefghijklmnopqrstu 'a + b'`
41
+ Then it should fail with:
42
+ """
43
+ Invalid function: name size can't be greater than 20 characters
44
+ """
45
+
46
+ Scenario Outline: Invalid function definition
47
+ Given I have no functions
48
+ When I run `fn create myfunction <definition>`
49
+ Then it should fail with:
50
+ """
51
+ Invalid function: definition must be a valid expression
52
+ """
53
+ Examples:
54
+ | definition |
55
+ | '1 +' |
56
+ | '(a + b' |
57
+ | 'a * b)' |
58
+ | '# &' |
59
+ | '* x' |
60
+ | '' |
61
+ | ' ' |
62
+ | ' ' |
63
+
64
+ Scenario Outline: Definition with division by zero
65
+ Given I have no functions
66
+ When I run `fn create myfunction '<definition>'`
67
+ Then it should fail with:
68
+ """
69
+ Invalid function: division by zero '<definition>'
70
+ """
71
+ Examples:
72
+ | definition |
73
+ | a / 0 |
74
+ | a / (2 - 2) |
@@ -0,0 +1,37 @@
1
+ Feature: Function deletion
2
+ In order to remove an unnecessary function
3
+ As a User
4
+ I want to delete a function
5
+
6
+ Scenario: Available function
7
+ Given I have the functions:
8
+ | name | definition |
9
+ | add | a + b |
10
+ | multiply | a * b |
11
+ When I run `fn delete add`
12
+ Then it should pass with:
13
+ """
14
+ Deleted function 'add'
15
+ """
16
+ And the following function should be available:
17
+ | name | definition |
18
+ | multiply | a * b |
19
+
20
+ Scenario: No functions available
21
+ Given I have no functions
22
+ When I run `fn delete add`
23
+ Then it should fail with:
24
+ """
25
+ Error: function 'add' doesn't exist
26
+ """
27
+
28
+ Scenario: Function doesn't exist
29
+ Given I have the functions:
30
+ | name | definition |
31
+ | add | a + b |
32
+ | multiply | a * b |
33
+ When I run `fn delete subtract`
34
+ Then it should fail with:
35
+ """
36
+ Error: function 'subtract' doesn't exist
37
+ """