functio 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
"""
|