keisan 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +90 -132
  3. data/bin/keisan +13 -2
  4. data/lib/keisan.rb +5 -0
  5. data/lib/keisan/ast.rb +11 -0
  6. data/lib/keisan/ast/assignment.rb +20 -55
  7. data/lib/keisan/ast/boolean.rb +16 -12
  8. data/lib/keisan/ast/cell.rb +17 -0
  9. data/lib/keisan/ast/cell_assignment.rb +70 -0
  10. data/lib/keisan/ast/function_assignment.rb +52 -0
  11. data/lib/keisan/ast/hash.rb +82 -0
  12. data/lib/keisan/ast/indexing.rb +26 -15
  13. data/lib/keisan/ast/line_builder.rb +22 -4
  14. data/lib/keisan/ast/list.rb +14 -7
  15. data/lib/keisan/ast/node.rb +13 -0
  16. data/lib/keisan/ast/null.rb +14 -0
  17. data/lib/keisan/ast/parent.rb +8 -3
  18. data/lib/keisan/ast/string.rb +10 -0
  19. data/lib/keisan/ast/variable.rb +4 -0
  20. data/lib/keisan/ast/variable_assignment.rb +62 -0
  21. data/lib/keisan/context.rb +16 -2
  22. data/lib/keisan/functions/default_registry.rb +4 -0
  23. data/lib/keisan/functions/enumerable_function.rb +56 -0
  24. data/lib/keisan/functions/filter.rb +34 -32
  25. data/lib/keisan/functions/map.rb +25 -31
  26. data/lib/keisan/functions/puts.rb +23 -0
  27. data/lib/keisan/functions/reduce.rb +29 -29
  28. data/lib/keisan/functions/registry.rb +4 -4
  29. data/lib/keisan/functions/sample.rb +5 -3
  30. data/lib/keisan/functions/to_h.rb +34 -0
  31. data/lib/keisan/interpreter.rb +42 -0
  32. data/lib/keisan/parser.rb +59 -50
  33. data/lib/keisan/parsing/compound_assignment.rb +15 -0
  34. data/lib/keisan/parsing/hash.rb +36 -0
  35. data/lib/keisan/repl.rb +1 -1
  36. data/lib/keisan/token.rb +1 -0
  37. data/lib/keisan/tokenizer.rb +23 -19
  38. data/lib/keisan/tokens/assignment.rb +21 -1
  39. data/lib/keisan/tokens/colon.rb +11 -0
  40. data/lib/keisan/tokens/unknown.rb +11 -0
  41. data/lib/keisan/variables/registry.rb +11 -6
  42. data/lib/keisan/version.rb +1 -1
  43. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3b56feddfbcabbb14a37f3b278a234d1c110bdc4
4
- data.tar.gz: 78ce88cb37946bc9356a78056a6ae2bbaa7ea788
3
+ metadata.gz: 900d86c9daad1cab75e6140a21785f6de67ead1c
4
+ data.tar.gz: f2c5f2abc85d46ce71aa651f0cc860363a8790bf
5
5
  SHA512:
6
- metadata.gz: 4fe9d5949164c273f8b7634595630758e12905be56adb2df12c3fd1ea0491ccb063ff7a1348ab27d88a1f1b6286d2a17e1c65565d192a1d8c0682c4cd4e75a3a
7
- data.tar.gz: 020dc6b00c5a8b24b98cbca79121a24321cea76067b31acca979a2f5f799f144b9ea0fb12f77fba474a5ce10f96aedc6375f065c0489e52f5c39112bff8922aa
6
+ metadata.gz: 4f5e7ea1fd844e7927af6eb5b66edacc53dac30541cb670d6208e43d0a9edb4611417943be232ba8188c275fa8890ee3c3e7f43a874ae32085f80b05092ecef6
7
+ data.tar.gz: 588daa93a53120d0456f38e66f5fa27d50b5e517516c3e0747519e51aeb5ca49dc317187e85ec420e5eec5bc722732138499e16188bf7271afbc4481ba1980bd
data/README.md CHANGED
@@ -7,7 +7,9 @@
7
7
  [![Maintainability](https://api.codeclimate.com/v1/badges/760e213d5ea81bca4480/maintainability)](https://codeclimate.com/github/project-eutopia/keisan/maintainability)
8
8
  [![Coverage Status](https://coveralls.io/repos/github/project-eutopia/keisan/badge.svg?branch=master)](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. This allows for safe evaluation of string representations of mathematical/logical expressions. It also has support for variables, functions, conditionals, and loops, making it a Turing complete programming language.
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
- The command `bin/keisan` will open up an interactive REPL. The commands you type in to this REPL are relayed to an internal `Keisan::Calculator` class and displayed back to you.
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
  ![alt text](screenshots/repl.png "Keisan built-in REPL")
35
38
 
39
+
36
40
  ### Calculator class
37
41
 
38
- The functionality of `keisan` can be demonstrated by using the `Keisan::Calculator` class. The `evaluate` method evaluates an expression by parsing it into an abstract syntax tree (AST), then evaluating any member functions/variables given. There is also a `simplify` method that allows undefined variables and functions to exist, and will just return the simplified AST.
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.children[0].class
58
- #=> Keisan::AST::Exponent
59
- ast.children[0].children[0].class
60
- #=> Keisan::AST::Variable
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 defines variables
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 will raise an error if an variable is not defined
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
- It will raise an error if a function is not defined
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(0)")
169
- #=> 1
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. It will evaluate each line separately, and the last line will be the the result of the total evaluation. Lines can be separated by newlines or semi-colons.
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. Inside a block, external variables are still visible and re-assignable, but new variable definitions remain local.
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. To assign to a local variable, you can use the `let` keyword. The difference is illustrated below.
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] = 22")
189
+ calculator.evaluate("a[1] += 10*a[2]")
223
190
  calculator.evaluate("a")
224
- #=> [1, 22, 3]
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("[1,3,5].map(x, y*x**2)").to_s
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
- calculator.evaluate("select([1,2,3,4], x, x % 2 == 0)")
261
+
262
+ calculator.evaluate("[1,2,3,4].select(x, x % 2 == 0)")
266
263
  #=> [2,4]
267
- calculator.evaluate("[-2,-1,0,1,2].filter(x, x > 0)")
268
- #=> [1,2]
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. This works just like the normal `while` loop.
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 = total + a[i]; i = i + 1}); 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("2 + 12 & 7")
311
- #=> 6
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 following builtin constants are defined
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
- ### Adding custom variables and functions
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.define_variable!("x", 5)
435
- calculator.evaluate("x + 1")
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. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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`. 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).
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. 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).
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/repl"
5
+ require "keisan/interpreter"
6
6
 
7
- Keisan::Repl.new.start
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)
@@ -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"