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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +9 -0
- data/COPYING +674 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +79 -0
- data/README.md +109 -0
- data/Rakefile +47 -0
- data/bin/fn +28 -0
- data/features/expression_evaluation.feature +58 -0
- data/features/function_creation.feature +74 -0
- data/features/function_deletion.feature +37 -0
- data/features/function_list.feature +35 -0
- data/features/function_use.feature +56 -0
- data/features/help_option.feature +13 -0
- data/features/step_definitions/steps.rb +36 -0
- data/features/support/env.rb +41 -0
- data/features/support/functio_world.rb +45 -0
- data/features/version_option.feature +19 -0
- data/functio.gemspec +43 -0
- data/lib/functio.rb +24 -0
- data/lib/functio/data_storage.rb +90 -0
- data/lib/functio/errors.rb +47 -0
- data/lib/functio/expression.rb +61 -0
- data/lib/functio/formatted_num.rb +39 -0
- data/lib/functio/functio_cli.rb +111 -0
- data/lib/functio/function.rb +104 -0
- data/lib/functio/function_repository.rb +73 -0
- data/lib/functio/version.rb +23 -0
- data/test/doubles/expression_double.rb +33 -0
- data/test/doubles/function_double.rb +34 -0
- data/test/doubles/storage_double.rb +36 -0
- data/test/doubles/test_expression_double.rb +30 -0
- data/test/doubles/test_function_double.rb +30 -0
- data/test/doubles/test_storage_double.rb +30 -0
- data/test/expression_interface_test.rb +30 -0
- data/test/interface_test_helper.rb +25 -0
- data/test/license_test_helper.rb +49 -0
- data/test/storable_interface_test.rb +30 -0
- data/test/storage_interface_test.rb +30 -0
- data/test/test_data_storage.rb +127 -0
- data/test/test_expression.rb +89 -0
- data/test/test_formatted_num.rb +56 -0
- data/test/test_function.rb +142 -0
- data/test/test_function_repository.rb +97 -0
- data/test/test_helper.rb +22 -0
- data/test/test_licenses_compatibility.rb +29 -0
- 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
|
data/Gemfile.lock
ADDED
@@ -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
|
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
+
"""
|