keisan 0.6.0 → 0.7.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 +4 -4
- data/README.md +90 -132
- data/bin/keisan +13 -2
- data/lib/keisan.rb +5 -0
- data/lib/keisan/ast.rb +11 -0
- data/lib/keisan/ast/assignment.rb +20 -55
- data/lib/keisan/ast/boolean.rb +16 -12
- data/lib/keisan/ast/cell.rb +17 -0
- data/lib/keisan/ast/cell_assignment.rb +70 -0
- data/lib/keisan/ast/function_assignment.rb +52 -0
- data/lib/keisan/ast/hash.rb +82 -0
- data/lib/keisan/ast/indexing.rb +26 -15
- data/lib/keisan/ast/line_builder.rb +22 -4
- data/lib/keisan/ast/list.rb +14 -7
- data/lib/keisan/ast/node.rb +13 -0
- data/lib/keisan/ast/null.rb +14 -0
- data/lib/keisan/ast/parent.rb +8 -3
- data/lib/keisan/ast/string.rb +10 -0
- data/lib/keisan/ast/variable.rb +4 -0
- data/lib/keisan/ast/variable_assignment.rb +62 -0
- data/lib/keisan/context.rb +16 -2
- data/lib/keisan/functions/default_registry.rb +4 -0
- data/lib/keisan/functions/enumerable_function.rb +56 -0
- data/lib/keisan/functions/filter.rb +34 -32
- data/lib/keisan/functions/map.rb +25 -31
- data/lib/keisan/functions/puts.rb +23 -0
- data/lib/keisan/functions/reduce.rb +29 -29
- data/lib/keisan/functions/registry.rb +4 -4
- data/lib/keisan/functions/sample.rb +5 -3
- data/lib/keisan/functions/to_h.rb +34 -0
- data/lib/keisan/interpreter.rb +42 -0
- data/lib/keisan/parser.rb +59 -50
- data/lib/keisan/parsing/compound_assignment.rb +15 -0
- data/lib/keisan/parsing/hash.rb +36 -0
- data/lib/keisan/repl.rb +1 -1
- data/lib/keisan/token.rb +1 -0
- data/lib/keisan/tokenizer.rb +23 -19
- data/lib/keisan/tokens/assignment.rb +21 -1
- data/lib/keisan/tokens/colon.rb +11 -0
- data/lib/keisan/tokens/unknown.rb +11 -0
- data/lib/keisan/variables/registry.rb +11 -6
- data/lib/keisan/version.rb +1 -1
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 900d86c9daad1cab75e6140a21785f6de67ead1c
|
4
|
+
data.tar.gz: f2c5f2abc85d46ce71aa651f0cc860363a8790bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f5e7ea1fd844e7927af6eb5b66edacc53dac30541cb670d6208e43d0a9edb4611417943be232ba8188c275fa8890ee3c3e7f43a874ae32085f80b05092ecef6
|
7
|
+
data.tar.gz: 588daa93a53120d0456f38e66f5fa27d50b5e517516c3e0747519e51aeb5ca49dc317187e85ec420e5eec5bc722732138499e16188bf7271afbc4481ba1980bd
|
data/README.md
CHANGED
@@ -7,7 +7,9 @@
|
|
7
7
|
[](https://codeclimate.com/github/project-eutopia/keisan/maintainability)
|
8
8
|
[](https://coveralls.io/github/project-eutopia/keisan?branch=master)
|
9
9
|
|
10
|
-
Keisan ([計算, to calculate](https://en.wiktionary.org/wiki/%E8%A8%88%E7%AE%97#Japanese)) is a Ruby library for parsing equations into an abstract syntax tree.
|
10
|
+
Keisan ([計算, to calculate](https://en.wiktionary.org/wiki/%E8%A8%88%E7%AE%97#Japanese)) is a Ruby library for parsing equations into an abstract syntax tree.
|
11
|
+
This allows for safe evaluation of string representations of mathematical/logical expressions.
|
12
|
+
It has support for variables, functions, conditionals, and loops, making it a Turing complete programming language.
|
11
13
|
|
12
14
|
## Installation
|
13
15
|
|
@@ -29,13 +31,17 @@ Or install it yourself as:
|
|
29
31
|
|
30
32
|
### REPL
|
31
33
|
|
32
|
-
|
34
|
+
To try `keisan` out locally, clone this repository and run the executable `bin/keisan` to open up an interactive REPL.
|
35
|
+
The commands you type in to this REPL are relayed to an internal `Keisan::Calculator` class and displayed back to you.
|
33
36
|
|
34
37
|

|
35
38
|
|
39
|
+
|
36
40
|
### Calculator class
|
37
41
|
|
38
|
-
|
42
|
+
This library is interacted with primarily through the `Keisan::Calculator` class.
|
43
|
+
The `evaluate` method evaluates an expression by parsing it into an abstract syntax tree (AST), and evaluating it.
|
44
|
+
There is also a `simplify` method that allows undefined variables and functions to exist, and will just return the simplified AST.
|
39
45
|
|
40
46
|
```ruby
|
41
47
|
calculator = Keisan::Calculator.new
|
@@ -50,29 +56,17 @@ For users who want access to the parsed abstract syntax tree, you can use the `a
|
|
50
56
|
```ruby
|
51
57
|
calculator = Keisan::Calculator.new
|
52
58
|
ast = calculator.ast("x**2+1")
|
53
|
-
ast.to_s
|
54
|
-
#=> "(x**2)+1"
|
55
59
|
ast.class
|
56
60
|
#=> Keisan::AST::Plus
|
57
|
-
ast.
|
58
|
-
#=>
|
59
|
-
ast.children
|
60
|
-
#=>
|
61
|
-
ast.children[0].children[0].name
|
62
|
-
#=> "x"
|
63
|
-
ast.children[0].children[1].class
|
64
|
-
#=> Keisan::AST::Number
|
65
|
-
ast.children[0].children[1].value
|
66
|
-
#=> 2
|
67
|
-
ast.children[1].class
|
68
|
-
#=> Keisan::AST::Number
|
69
|
-
ast.children[1].value
|
70
|
-
#=> 1
|
61
|
+
ast.to_s
|
62
|
+
#=> "(x**2)+1"
|
63
|
+
ast.children.map(&:to_s)
|
64
|
+
#=> ["x**2", "1"]
|
71
65
|
```
|
72
66
|
|
73
67
|
##### Specifying variables
|
74
68
|
|
75
|
-
Passing in a hash of variable (`name`, `value`) pairs to the `evaluate` method
|
69
|
+
Passing in a hash of variable (`name`, `value`) pairs to the `evaluate` method is one way of defining variables
|
76
70
|
|
77
71
|
```ruby
|
78
72
|
calculator = Keisan::Calculator.new
|
@@ -80,15 +74,7 @@ calculator.evaluate("3*x + y**2", x: -2.5, y: 3)
|
|
80
74
|
#=> 1.5
|
81
75
|
```
|
82
76
|
|
83
|
-
It
|
84
|
-
|
85
|
-
```ruby
|
86
|
-
calculator = Keisan::Calculator.new
|
87
|
-
calculator.evaluate("x + 1")
|
88
|
-
#=> Keisan::Exceptions::UndefinedVariableError: x
|
89
|
-
```
|
90
|
-
|
91
|
-
It is also possible to define variables in the string expression itself
|
77
|
+
It is also possible to define variables in the string expression itself using the assignment `=` operator
|
92
78
|
|
93
79
|
```ruby
|
94
80
|
calculator = Keisan::Calculator.new
|
@@ -97,6 +83,7 @@ calculator.evaluate("3*x + 1")
|
|
97
83
|
#=> 61
|
98
84
|
```
|
99
85
|
|
86
|
+
|
100
87
|
##### Specifying functions
|
101
88
|
|
102
89
|
Just like variables, functions can be defined by passing a `Proc` object as follows
|
@@ -107,42 +94,21 @@ calculator.evaluate("2*f(1+2) + 4", f: Proc.new {|x| x**2})
|
|
107
94
|
#=> 22
|
108
95
|
```
|
109
96
|
|
110
|
-
|
97
|
+
Note that functions work in both regular (`f(x)`) and postfix (`x.f()`) notation, where for example `a.f(b,c)` is translated internally to `f(a,b,c)`.
|
98
|
+
The postfix notation requires the function to take at least one argument, and if there is only one argument to the function then the braces can be left off: `x.f`.
|
111
99
|
|
112
100
|
```ruby
|
113
101
|
calculator = Keisan::Calculator.new
|
114
|
-
calculator.evaluate("f(2) + 1")
|
115
|
-
#=> Keisan::Exceptions::UndefinedFunctionError: f
|
116
|
-
```
|
117
|
-
|
118
|
-
Note that functions work in both regular (`f(x)`) and postfix (`x.f()`) notation. The postfix notation requires the function to take at least one argument. In the case of `a.f(b,c)`, this is translated internally to `f(a,b,c)`. If there is only a single argument to the function, the braces can be left off: `x.f`.
|
119
|
-
|
120
|
-
```ruby
|
121
|
-
calculator = Keisan::Calculator.new
|
122
|
-
calculator.evaluate("[1,3,5,7].size()")
|
123
|
-
#=> 4
|
124
102
|
calculator.evaluate("[1,3,5,7].size")
|
125
103
|
#=> 4
|
126
|
-
```
|
127
|
-
|
128
|
-
It is even possible to do more complicated things like follows
|
129
|
-
|
130
|
-
```ruby
|
131
|
-
calculator = Keisan::Calculator.new
|
132
104
|
calculator.define_function!("f", Proc.new {|x| [[x-1,x+1], [x-2,x,x+2]]})
|
133
|
-
calculator.evaluate("4.f")
|
134
|
-
#=> [[3,5], [2,4,6]]
|
135
105
|
calculator.evaluate("4.f[0]")
|
136
106
|
#=> [3,5]
|
137
|
-
calculator.evaluate("4.f[0].size")
|
138
|
-
#=> 2
|
139
|
-
calculator.evaluate("4.f[1]")
|
140
|
-
#=> [2,4,6]
|
141
107
|
calculator.evaluate("4.f[1].size")
|
142
108
|
#=> 3
|
143
109
|
```
|
144
110
|
|
145
|
-
Like variables, it is also possible to define functions in the string expression itself
|
111
|
+
Like variables, it is also possible to define functions in the string expression itself using the assignment operator `=`
|
146
112
|
|
147
113
|
```ruby
|
148
114
|
calculator = Keisan::Calculator.new
|
@@ -165,19 +131,17 @@ calculator.evaluate("my_fact(n) = if (n > 1, n*my_fact(n-1), 1)")
|
|
165
131
|
|
166
132
|
calculator = Keisan::Calculator.new(allow_recursive: true)
|
167
133
|
calculator.evaluate("my_fact(n) = if (n > 1, n*my_fact(n-1), 1)")
|
168
|
-
calculator.evaluate("my_fact(
|
169
|
-
#=>
|
170
|
-
calculator.evaluate("my_fact(1)")
|
171
|
-
#=> 1
|
172
|
-
calculator.evaluate("my_fact(2)")
|
173
|
-
#=> 2
|
134
|
+
calculator.evaluate("my_fact(4)")
|
135
|
+
#=> 24
|
174
136
|
calculator.evaluate("my_fact(5)")
|
175
137
|
#=> 120
|
176
138
|
```
|
177
139
|
|
178
140
|
##### Multiple lines and blocks
|
179
141
|
|
180
|
-
Keisan understands strings which contain multiple lines.
|
142
|
+
Keisan understands strings which contain multiple lines.
|
143
|
+
It will evaluate each line separately, and the last line will be the the result of the total evaluation.
|
144
|
+
Lines can be separated by newlines or semi-colons.
|
181
145
|
|
182
146
|
```ruby
|
183
147
|
calculator = Keisan::Calculator.new
|
@@ -185,7 +149,8 @@ calculator.evaluate("x = 2; y = 5\n x+y")
|
|
185
149
|
#=> 7
|
186
150
|
```
|
187
151
|
|
188
|
-
The use of curly braces `{}` can be used to create block which has a new closure where variable definitions are local to the block itself.
|
152
|
+
The use of curly braces `{}` can be used to create block which has a new closure where variable definitions are local to the block itself.
|
153
|
+
Inside a block, external variables are still visible and re-assignable, but new variable definitions remain local.
|
189
154
|
|
190
155
|
```ruby
|
191
156
|
calculator = Keisan::Calculator.new
|
@@ -198,7 +163,9 @@ calculator.evaluate("a")
|
|
198
163
|
#=> Keisan::Exceptions::UndefinedVariableError: a
|
199
164
|
```
|
200
165
|
|
201
|
-
By default assigning to a variable or function will bubble up to the first definition available in the parent scopes.
|
166
|
+
By default assigning to a variable or function will bubble up to the first definition available in the parent scopes.
|
167
|
+
To assign to a local variable instead of modifying an existing variable out of the closure, you can use the `let` keyword.
|
168
|
+
The difference is illustrated below.
|
202
169
|
|
203
170
|
```ruby
|
204
171
|
calculator = Keisan::Calculator.new
|
@@ -219,9 +186,9 @@ calculator.evaluate("[2, 3, 5, 8]")
|
|
219
186
|
calculator.evaluate("[[1,2,3],[4,5,6],[7,8,9]][1][2]")
|
220
187
|
#=> 6
|
221
188
|
calculator.evaluate("a = [1,2,3]")
|
222
|
-
calculator.evaluate("a[1]
|
189
|
+
calculator.evaluate("a[1] += 10*a[2]")
|
223
190
|
calculator.evaluate("a")
|
224
|
-
#=> [1,
|
191
|
+
#=> [1, 32, 3]
|
225
192
|
```
|
226
193
|
|
227
194
|
They can also be concatenated using the `+` operator
|
@@ -254,20 +221,53 @@ calculator.evaluate("range(0,10,2)")
|
|
254
221
|
#=> [0,2,4,6,8]
|
255
222
|
```
|
256
223
|
|
224
|
+
##### Hashes
|
225
|
+
|
226
|
+
Keisan also supports associative arrays (hashes), which maps keys to values.
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
calculator = Keisan::Calculator.new
|
230
|
+
calculator.evaluate("my_hash = {777: 3*4, \"bar\": \"hello world\"}")
|
231
|
+
calculator.evaluate("my_hash[777]")
|
232
|
+
#=> 12
|
233
|
+
calculator.evaluate("s = 'ba'")
|
234
|
+
calculator.evaluate("my_hash[s + 'r']")
|
235
|
+
#=> "hello world"
|
236
|
+
calculator.evaluate("my_hash['baz']")
|
237
|
+
#=> nil
|
238
|
+
calculator.evaluate("my_hash['baz'] = 999")
|
239
|
+
calculator.evaluate("my_hash['baz']")
|
240
|
+
#=> 999
|
241
|
+
```
|
242
|
+
|
243
|
+
There is also a `to_h` method which converts a list of key value pairs into a hash.
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
calculator = Keisan::Calculator.new
|
247
|
+
calculator.evaluate("range(1, 6).map(x, [x, x**2]).to_h")
|
248
|
+
#=> {1 => 1, 2 => 4, 3 => 9, 4 => 16, 5 => 25}
|
249
|
+
```
|
250
|
+
|
251
|
+
##### Functional programming methods
|
252
|
+
|
257
253
|
Keisan also supports the basic functional programming operators `map` (or `collect`), `filter` (or `select`), and `reduce` (or `inject`).
|
258
254
|
|
259
255
|
```ruby
|
260
256
|
calculator = Keisan::Calculator.new
|
261
257
|
calculator.evaluate("map([1,3,5], x, 2*x)")
|
262
258
|
#=> [2,6,10]
|
263
|
-
calculator.simplify("
|
259
|
+
calculator.simplify("{'a': 1, 'b': 3, 'c': 5}.collect(k, v, y*v**2)").to_s
|
264
260
|
#=> "[y,9*y,25*y]"
|
265
|
-
|
261
|
+
|
262
|
+
calculator.evaluate("[1,2,3,4].select(x, x % 2 == 0)")
|
266
263
|
#=> [2,4]
|
267
|
-
calculator.evaluate("
|
268
|
-
#=>
|
264
|
+
calculator.evaluate("filter({'a': 1, 'bb': 4, 'ccc': 9}, k, v, k.size == 2)")
|
265
|
+
#=> {"bb" => 4}
|
266
|
+
|
269
267
|
calculator.evaluate("[1,2,3,4,5].inject(1, total, x, total*x)")
|
270
268
|
#=> 120
|
269
|
+
calculator.evaluate("{'foo': 'hello', 'bar': ' world'}.reduce('', res, k, v, res + v)")
|
270
|
+
#=> "hello world"
|
271
271
|
```
|
272
272
|
|
273
273
|
##### Logical operations
|
@@ -292,11 +292,11 @@ calculator.evaluate("2 + if(1 > 0, 10, 29)")
|
|
292
292
|
#=> 12
|
293
293
|
```
|
294
294
|
|
295
|
-
For looping, you can use the basic `while` loop, which has an expression that evaluates to a boolean as the first argument, and any expression in the second argument.
|
295
|
+
For looping, you can use the basic `while` loop, which has an expression that evaluates to a boolean as the first argument, and any expression in the second argument.
|
296
296
|
|
297
297
|
```ruby
|
298
298
|
calculator = Keisan::Calculator.new
|
299
|
-
calculator.evaluate("my_sum(a) = {let i = 0; let total = 0; while(i < a.size, {total
|
299
|
+
calculator.evaluate("my_sum(a) = {let i = 0; let total = 0; while(i < a.size, {total += a[i]; i += 1}); total}")
|
300
300
|
calculator.evaluate("my_sum([1,3,5,7,9])")
|
301
301
|
#=> 25
|
302
302
|
```
|
@@ -307,8 +307,8 @@ The basic bitwise operations, NOT `~`, OR `|`, XOR `^`, and AND `&` are also ava
|
|
307
307
|
|
308
308
|
```ruby
|
309
309
|
calculator = Keisan::Calculator.new
|
310
|
-
calculator.evaluate("
|
311
|
-
#=>
|
310
|
+
calculator.evaluate("0b00001111 & 0b10101010")
|
311
|
+
#=> 10
|
312
312
|
```
|
313
313
|
|
314
314
|
##### String
|
@@ -368,19 +368,7 @@ calculator.evaluate("log10(1000)")
|
|
368
368
|
#=> 3.0
|
369
369
|
```
|
370
370
|
|
371
|
-
Furthermore, the
|
372
|
-
|
373
|
-
```ruby
|
374
|
-
calculator = Keisan::Calculator.new
|
375
|
-
calculator.evaluate("PI")
|
376
|
-
#=> 3.141592653589793
|
377
|
-
calculator.evaluate("E")
|
378
|
-
#=> 2.718281828459045
|
379
|
-
calculator.evaluate("I")
|
380
|
-
#=> (0+1i)
|
381
|
-
```
|
382
|
-
|
383
|
-
This allows for simple calculations like
|
371
|
+
Furthermore, the constants `PI`, `E`, and `I` are included.
|
384
372
|
|
385
373
|
```ruby
|
386
374
|
calculator = Keisan::Calculator.new
|
@@ -425,63 +413,26 @@ calculator.evaluate("replace(diff(f(2*t, t+1), t), t, 3)")
|
|
425
413
|
#=> 1+8*3
|
426
414
|
```
|
427
415
|
|
428
|
-
|
429
|
-
|
430
|
-
The `Keisan::Calculator` class has a single `Keisan::Context` object in its `context` attribute. This class is used to store local variables and functions. These can be stored using either the `define_variable!` or `define_function!` methods, or by using the assignment operator `=` in an expression that is evaluated. As an example of pre-defining some variables and functions, see the following
|
416
|
+
There is also a `puts` function that can be used to output the result of an expression to STDOUT.
|
431
417
|
|
432
418
|
```ruby
|
433
419
|
calculator = Keisan::Calculator.new
|
434
|
-
calculator.
|
435
|
-
calculator.evaluate("x
|
436
|
-
#=> 6
|
437
|
-
calculator.evaluate("x + 1", x: 10)
|
438
|
-
#=> 11
|
439
|
-
calculator.evaluate("x + 1")
|
440
|
-
#=> 6
|
441
|
-
|
442
|
-
calculator.evaluate("x = y = 10")
|
443
|
-
#=> 10
|
444
|
-
calculator.evaluate("x + y")
|
445
|
-
#=> 20
|
446
|
-
calculator.evaluate("x + y", y: 100)
|
447
|
-
#=> 110
|
448
|
-
calculator.evaluate("x + y")
|
449
|
-
#=> 20
|
420
|
+
calculator.evaluate("x = 5")
|
421
|
+
calculator.evaluate("puts x**2") # prints "25\n" to STDOUT
|
450
422
|
```
|
451
423
|
|
452
|
-
Notice how when passing variable values directly to the `evaluate` method, it only shadows the value of 5 for that specific calculation. The same thing works for functions
|
453
|
-
|
454
|
-
```ruby
|
455
|
-
calculator = Keisan::Calculator.new
|
456
|
-
calculator.define_function!("f", Proc.new {|x| 3*x})
|
457
|
-
#=> #<Keisan::Function:0x005570f935ecc8 @function_proc=#<Proc:0x005570f935ecf0@(pry):6>, @name="f">
|
458
|
-
calculator.evaluate("f(2)")
|
459
|
-
#=> 6
|
460
|
-
calculator.evaluate("f(2)", f: Proc.new {|x| 10*x})
|
461
|
-
#=> 20
|
462
|
-
calculator.evaluate("f(2)")
|
463
|
-
#=> 6
|
464
|
-
|
465
|
-
calculator.evaluate("f(x) = x + x**2")
|
466
|
-
#=> nil
|
467
|
-
calculator.evaluate("f(3)")
|
468
|
-
#=> 12
|
469
|
-
calculator.evaluate("f(3)", f: Proc.new {|x| 10*x})
|
470
|
-
#=> 30
|
471
|
-
calculator.evaluate("f(3)")
|
472
|
-
#=> 12
|
473
|
-
```
|
474
424
|
|
475
425
|
## Supported elements/operators
|
476
426
|
|
477
427
|
`keisan` supports the following operators and elements.
|
478
428
|
|
479
|
-
#### Numbers, variables, functions, lists
|
429
|
+
#### Numbers, variables, brackets, functions, lists, hashes
|
480
430
|
- `150`, `-5.67`, `6e-5`: regular numbers
|
481
431
|
- `x`, `_myvar1`: variables
|
482
432
|
- `(` and `)`: round brackets for grouping parts to evaluate first
|
483
|
-
- `[0, 3, 6, 9]`: square brackets with comma separated values to denote lists
|
484
433
|
- `f(x,y,z)`, `my_function(max([2.5, 5.5]))`, `[2,4,6,8].size`: functions using `(` `)` brackets (optional if using postfix notation and only takes a single argument)
|
434
|
+
- `[0, 3, 6, 9]`: square brackets with comma separated values to denote lists
|
435
|
+
- `{'foo': 11, 'bar': 22}`: curly brackets containing key/value pairs creates a hash
|
485
436
|
|
486
437
|
#### Arithmetic operators
|
487
438
|
- `+`, `-`, `*`, `/`: regular arithmetic operators
|
@@ -499,18 +450,25 @@ calculator.evaluate("f(3)")
|
|
499
450
|
- `&`, `|`, `^`: bitwise **and**, **or**, **xor** operators
|
500
451
|
- `~`: unary bitwise not
|
501
452
|
|
502
|
-
#### Indexing of arrays
|
453
|
+
#### Indexing of arrays/hashes
|
503
454
|
- `list[i]`: for accessing elements in an array
|
455
|
+
- `hash[k]`: for accessing elements in a hash
|
504
456
|
|
505
457
|
#### Assignment
|
506
458
|
- `=`: can be used to define variables and functions
|
459
|
+
- `+=`: can be used in combination with operators above
|
460
|
+
|
507
461
|
|
508
462
|
## Development
|
509
463
|
|
510
|
-
After checking out the repository, run `bin/setup` to install dependencies.
|
464
|
+
After checking out the repository, run `bin/setup` to install dependencies.
|
465
|
+
Then, run `rake spec` to run the tests.
|
466
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment with the library pre-loaded.
|
511
467
|
|
512
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
468
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
469
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
513
470
|
|
514
471
|
## Contributing
|
515
472
|
|
516
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/project-eutopia/keisan.
|
473
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/project-eutopia/keisan.
|
474
|
+
If there is any functionality you would like (e.g. new functions), feel free to open a [new issue](https://github.com/project-eutopia/keisan/issues/new).
|
data/bin/keisan
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "keisan"
|
5
|
-
require "keisan/
|
5
|
+
require "keisan/interpreter"
|
6
6
|
|
7
|
-
|
7
|
+
file_name = nil
|
8
|
+
allow_recursive = false
|
9
|
+
|
10
|
+
ARGV.each do |arg|
|
11
|
+
if arg == "--allow_recursive"
|
12
|
+
allow_recursive = true
|
13
|
+
else
|
14
|
+
file_name = arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Keisan::Interpreter.new(allow_recursive: allow_recursive).run(file_name)
|
data/lib/keisan.rb
CHANGED
@@ -48,6 +48,7 @@ require "keisan/ast/logical_less_than_or_equal_to"
|
|
48
48
|
require "keisan/ast/logical_greater_than_or_equal_to"
|
49
49
|
require "keisan/ast/function"
|
50
50
|
require "keisan/ast/list"
|
51
|
+
require "keisan/ast/hash"
|
51
52
|
require "keisan/ast/indexing"
|
52
53
|
|
53
54
|
require "keisan/ast/line_builder"
|
@@ -65,6 +66,7 @@ require "keisan/context"
|
|
65
66
|
|
66
67
|
require "keisan/token"
|
67
68
|
require "keisan/tokens/comma"
|
69
|
+
require "keisan/tokens/colon"
|
68
70
|
require "keisan/tokens/dot"
|
69
71
|
require "keisan/tokens/group"
|
70
72
|
require "keisan/tokens/number"
|
@@ -78,6 +80,7 @@ require "keisan/tokens/logical_operator"
|
|
78
80
|
require "keisan/tokens/bitwise_operator"
|
79
81
|
require "keisan/tokens/word"
|
80
82
|
require "keisan/tokens/line_separator"
|
83
|
+
require "keisan/tokens/unknown"
|
81
84
|
|
82
85
|
require "keisan/tokenizer"
|
83
86
|
|
@@ -98,6 +101,7 @@ require "keisan/parsing/round_group"
|
|
98
101
|
require "keisan/parsing/square_group"
|
99
102
|
require "keisan/parsing/curly_group"
|
100
103
|
require "keisan/parsing/list"
|
104
|
+
require "keisan/parsing/hash"
|
101
105
|
require "keisan/parsing/indexing"
|
102
106
|
require "keisan/parsing/argument"
|
103
107
|
require "keisan/parsing/line_separator"
|
@@ -105,6 +109,7 @@ require "keisan/parsing/line_separator"
|
|
105
109
|
require "keisan/parsing/operator"
|
106
110
|
|
107
111
|
require "keisan/parsing/assignment"
|
112
|
+
require "keisan/parsing/compound_assignment"
|
108
113
|
|
109
114
|
require "keisan/parsing/unary_operator"
|
110
115
|
require "keisan/parsing/unary_plus"
|