keisan 0.3.0 → 0.4.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +57 -9
  3. data/lib/keisan.rb +21 -12
  4. data/lib/keisan/ast.rb +50 -0
  5. data/lib/keisan/ast/arithmetic_operator.rb +0 -3
  6. data/lib/keisan/ast/assignment.rb +72 -0
  7. data/lib/keisan/ast/bitwise_and.rb +4 -4
  8. data/lib/keisan/ast/bitwise_operator.rb +0 -3
  9. data/lib/keisan/ast/bitwise_or.rb +4 -4
  10. data/lib/keisan/ast/bitwise_xor.rb +4 -4
  11. data/lib/keisan/ast/boolean.rb +25 -1
  12. data/lib/keisan/ast/builder.rb +98 -63
  13. data/lib/keisan/ast/constant_literal.rb +13 -0
  14. data/lib/keisan/ast/exponent.rb +62 -8
  15. data/lib/keisan/ast/function.rb +37 -26
  16. data/lib/keisan/ast/functions/diff.rb +57 -0
  17. data/lib/keisan/ast/functions/if.rb +47 -0
  18. data/lib/keisan/ast/indexing.rb +44 -4
  19. data/lib/keisan/ast/list.rb +4 -0
  20. data/lib/keisan/ast/literal.rb +8 -0
  21. data/lib/keisan/ast/logical_and.rb +9 -4
  22. data/lib/keisan/ast/logical_equal.rb +4 -4
  23. data/lib/keisan/ast/logical_greater_than.rb +4 -4
  24. data/lib/keisan/ast/logical_greater_than_or_equal_to.rb +4 -4
  25. data/lib/keisan/ast/logical_less_than.rb +4 -4
  26. data/lib/keisan/ast/logical_less_than_or_equal_to.rb +4 -4
  27. data/lib/keisan/ast/logical_not_equal.rb +4 -4
  28. data/lib/keisan/ast/logical_operator.rb +0 -3
  29. data/lib/keisan/ast/logical_or.rb +10 -5
  30. data/lib/keisan/ast/modulo.rb +4 -4
  31. data/lib/keisan/ast/node.rb +132 -20
  32. data/lib/keisan/ast/null.rb +1 -1
  33. data/lib/keisan/ast/number.rb +172 -1
  34. data/lib/keisan/ast/operator.rb +66 -8
  35. data/lib/keisan/ast/parent.rb +50 -0
  36. data/lib/keisan/ast/plus.rb +38 -4
  37. data/lib/keisan/ast/string.rb +10 -1
  38. data/lib/keisan/ast/times.rb +47 -4
  39. data/lib/keisan/ast/unary_bitwise_not.rb +9 -1
  40. data/lib/keisan/ast/unary_identity.rb +18 -1
  41. data/lib/keisan/ast/unary_inverse.rb +35 -1
  42. data/lib/keisan/ast/unary_logical_not.rb +5 -1
  43. data/lib/keisan/ast/unary_minus.rb +31 -1
  44. data/lib/keisan/ast/unary_operator.rb +29 -1
  45. data/lib/keisan/ast/unary_plus.rb +14 -1
  46. data/lib/keisan/ast/variable.rb +44 -0
  47. data/lib/keisan/calculator.rb +2 -2
  48. data/lib/keisan/context.rb +32 -16
  49. data/lib/keisan/evaluator.rb +10 -65
  50. data/lib/keisan/exceptions.rb +2 -0
  51. data/lib/keisan/function.rb +11 -5
  52. data/lib/keisan/function_definition_context.rb +34 -0
  53. data/lib/keisan/functions/default_registry.rb +13 -5
  54. data/lib/keisan/functions/diff.rb +82 -0
  55. data/lib/keisan/functions/expression_function.rb +63 -0
  56. data/lib/keisan/functions/if.rb +62 -0
  57. data/lib/keisan/functions/proc_function.rb +52 -0
  58. data/lib/keisan/functions/rand.rb +1 -1
  59. data/lib/keisan/functions/registry.rb +20 -10
  60. data/lib/keisan/functions/replace.rb +49 -0
  61. data/lib/keisan/functions/sample.rb +1 -1
  62. data/lib/keisan/parser.rb +13 -1
  63. data/lib/keisan/parsing/assignment.rb +9 -0
  64. data/lib/keisan/parsing/operator.rb +8 -0
  65. data/lib/keisan/parsing/unary_operator.rb +1 -1
  66. data/lib/keisan/tokenizer.rb +1 -0
  67. data/lib/keisan/tokens/assignment.rb +15 -0
  68. data/lib/keisan/variables/default_registry.rb +4 -4
  69. data/lib/keisan/variables/registry.rb +17 -8
  70. data/lib/keisan/version.rb +1 -1
  71. metadata +15 -3
  72. data/lib/keisan/ast/priorities.rb +0 -27
@@ -1,6 +1,6 @@
1
1
  module Keisan
2
2
  module Functions
3
- class Sample < Keisan::Function
3
+ class Sample < ProcFunction
4
4
  def initialize
5
5
  @name = "sample"
6
6
  end
@@ -17,6 +17,7 @@ module Keisan
17
17
  @components = []
18
18
 
19
19
  parse_components!
20
+ remove_unary_identity!
20
21
  end
21
22
 
22
23
  def ast
@@ -36,6 +37,12 @@ module Keisan
36
37
  end
37
38
  end
38
39
 
40
+ def remove_unary_identity!
41
+ @components = @components.select do |component|
42
+ !component.is_a?(Keisan::Parsing::Operator) || !(component.node_class <= Keisan::AST::UnaryIdentity)
43
+ end
44
+ end
45
+
39
46
  # Elements are groups of tokens separated by (non-unary) operators
40
47
  # The following are basic elements:
41
48
  # number
@@ -58,8 +65,10 @@ module Keisan
58
65
  end
59
66
 
60
67
  elsif @components[-1].is_a?(Parsing::UnaryOperator)
61
- # Expect an element
68
+ # Expect an element or another unary operator
62
69
  case token.type
70
+ when :operator
71
+ add_unary_operator_to_components!(token)
63
72
  when :number, :string, :word, :group, :null, :boolean
64
73
  add_element_to_components!(token)
65
74
  else
@@ -154,6 +163,9 @@ module Keisan
154
163
 
155
164
  def add_operator_to_components!(token)
156
165
  case token.operator_type
166
+ # Assignment
167
+ when :"="
168
+ @components << Keisan::Parsing::Assignment.new
157
169
  # Arithmetic
158
170
  when :+
159
171
  @components << Keisan::Parsing::Plus.new
@@ -0,0 +1,9 @@
1
+ module Keisan
2
+ module Parsing
3
+ class Assignment < Operator
4
+ def node_class
5
+ Keisan::AST::Assignment
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,10 +1,18 @@
1
1
  module Keisan
2
2
  module Parsing
3
3
  class Operator < Component
4
+ def arity
5
+ node_class.arity
6
+ end
7
+
4
8
  def priority
5
9
  node_class.priority
6
10
  end
7
11
 
12
+ def associativity
13
+ node_class.associativity
14
+ end
15
+
8
16
  def node_class
9
17
  raise Keisan::Exceptions::NotImplementedError.new
10
18
  end
@@ -1,6 +1,6 @@
1
1
  module Keisan
2
2
  module Parsing
3
- class UnaryOperator < Component
3
+ class UnaryOperator < Operator
4
4
  def node_class
5
5
  raise Keisan::Exponent::NotImplementedError.new
6
6
  end
@@ -10,6 +10,7 @@ module Keisan
10
10
  Tokens::ArithmeticOperator,
11
11
  Tokens::LogicalOperator,
12
12
  Tokens::BitwiseOperator,
13
+ Tokens::Assignment,
13
14
  Tokens::Comma,
14
15
  Tokens::Dot
15
16
  ]
@@ -0,0 +1,15 @@
1
+ module Keisan
2
+ module Tokens
3
+ class Assignment < Operator
4
+ REGEX = /(\=)/
5
+
6
+ def self.regex
7
+ REGEX
8
+ end
9
+
10
+ def operator_type
11
+ :"="
12
+ end
13
+ end
14
+ end
15
+ end
@@ -7,13 +7,13 @@ module Keisan
7
7
  end
8
8
 
9
9
  VARIABLES = {
10
- "pi" => Math::PI,
11
- "e" => Math::E,
12
- "i" => Complex(0,1)
10
+ "PI" => Math::PI,
11
+ "E" => Math::E,
12
+ "I" => Complex(0,1)
13
13
  }
14
14
 
15
15
  def self.registry
16
- @registry ||= Registry.new(variables: VARIABLES, parent: nil).freeze
16
+ @registry ||= Registry.new(variables: VARIABLES, parent: nil, force: true).freeze
17
17
  end
18
18
  end
19
19
  end
@@ -1,19 +1,23 @@
1
1
  module Keisan
2
2
  module Variables
3
3
  class Registry
4
- def initialize(variables: {}, parent: nil, use_defaults: true)
4
+ def initialize(variables: {}, parent: nil, use_defaults: true, force: false)
5
5
  @hash = {}
6
6
  @parent = parent
7
7
  @use_defaults = use_defaults
8
8
 
9
9
  variables.each do |name, value|
10
- register!(name, value)
10
+ register!(name, value, force: force)
11
11
  end
12
12
  end
13
13
 
14
14
  def [](name)
15
15
  return @hash[name] if @hash.has_key?(name)
16
- return @parent[name] if !@parent.nil? && @parent.has_name?(name)
16
+
17
+ if @parent && (parent_value = @parent[name])
18
+ return parent_value
19
+ end
20
+
17
21
  return default_registry[name] if @use_defaults && default_registry.has_name?(name)
18
22
  raise Keisan::Exceptions::UndefinedVariableError.new name
19
23
  end
@@ -24,16 +28,21 @@ module Keisan
24
28
  false
25
29
  end
26
30
 
31
+ def register!(name, value, force: false)
32
+ raise Keisan::Exceptions::UnmodifiableError.new("Cannot modify frozen variables registry") if frozen?
33
+ if !force && @use_defaults && default_registry.has_name?(name)
34
+ raise Keisan::Exceptions::UnmodifiableError.new("Cannot overwrite default variable")
35
+ end
36
+ self[name.to_s] = value
37
+ end
38
+
39
+ protected
40
+
27
41
  # For checking if locally defined
28
42
  def has_name?(name)
29
43
  @hash.has_key?(name)
30
44
  end
31
45
 
32
- def register!(name, value)
33
- raise Keisan::Exceptions::UnmodifiableError.new("Cannot modify frozen variables registry") if frozen?
34
- self[name.to_s] = value
35
- end
36
-
37
46
  private
38
47
 
39
48
  def []=(name, value)
@@ -1,3 +1,3 @@
1
1
  module Keisan
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keisan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Locke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-25 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -112,15 +112,20 @@ files:
112
112
  - bin/setup
113
113
  - keisan.gemspec
114
114
  - lib/keisan.rb
115
+ - lib/keisan/ast.rb
115
116
  - lib/keisan/ast/arithmetic_operator.rb
117
+ - lib/keisan/ast/assignment.rb
116
118
  - lib/keisan/ast/bitwise_and.rb
117
119
  - lib/keisan/ast/bitwise_operator.rb
118
120
  - lib/keisan/ast/bitwise_or.rb
119
121
  - lib/keisan/ast/bitwise_xor.rb
120
122
  - lib/keisan/ast/boolean.rb
121
123
  - lib/keisan/ast/builder.rb
124
+ - lib/keisan/ast/constant_literal.rb
122
125
  - lib/keisan/ast/exponent.rb
123
126
  - lib/keisan/ast/function.rb
127
+ - lib/keisan/ast/functions/diff.rb
128
+ - lib/keisan/ast/functions/if.rb
124
129
  - lib/keisan/ast/indexing.rb
125
130
  - lib/keisan/ast/list.rb
126
131
  - lib/keisan/ast/literal.rb
@@ -140,7 +145,6 @@ files:
140
145
  - lib/keisan/ast/operator.rb
141
146
  - lib/keisan/ast/parent.rb
142
147
  - lib/keisan/ast/plus.rb
143
- - lib/keisan/ast/priorities.rb
144
148
  - lib/keisan/ast/string.rb
145
149
  - lib/keisan/ast/times.rb
146
150
  - lib/keisan/ast/unary_bitwise_not.rb
@@ -156,13 +160,20 @@ files:
156
160
  - lib/keisan/evaluator.rb
157
161
  - lib/keisan/exceptions.rb
158
162
  - lib/keisan/function.rb
163
+ - lib/keisan/function_definition_context.rb
159
164
  - lib/keisan/functions/default_registry.rb
165
+ - lib/keisan/functions/diff.rb
166
+ - lib/keisan/functions/expression_function.rb
167
+ - lib/keisan/functions/if.rb
168
+ - lib/keisan/functions/proc_function.rb
160
169
  - lib/keisan/functions/rand.rb
161
170
  - lib/keisan/functions/registry.rb
171
+ - lib/keisan/functions/replace.rb
162
172
  - lib/keisan/functions/sample.rb
163
173
  - lib/keisan/parser.rb
164
174
  - lib/keisan/parsing/argument.rb
165
175
  - lib/keisan/parsing/arithmetic_operator.rb
176
+ - lib/keisan/parsing/assignment.rb
166
177
  - lib/keisan/parsing/bitwise_and.rb
167
178
  - lib/keisan/parsing/bitwise_not.rb
168
179
  - lib/keisan/parsing/bitwise_not_not.rb
@@ -209,6 +220,7 @@ files:
209
220
  - lib/keisan/token.rb
210
221
  - lib/keisan/tokenizer.rb
211
222
  - lib/keisan/tokens/arithmetic_operator.rb
223
+ - lib/keisan/tokens/assignment.rb
212
224
  - lib/keisan/tokens/bitwise_operator.rb
213
225
  - lib/keisan/tokens/boolean.rb
214
226
  - lib/keisan/tokens/comma.rb
@@ -1,27 +0,0 @@
1
- module Keisan
2
- module AST
3
- class Priorities
4
- PRIORITIES = {
5
- "**": 100,
6
- "*": 95,
7
- "%": 90,
8
- "+": 85,
9
- "&": 80,
10
- "|": 75,
11
- "^": 70,
12
- ">": 65,
13
- ">=": 60,
14
- "<": 55,
15
- "<=": 50,
16
- "==": 45,
17
- "!=": 40,
18
- "&&": 35,
19
- "||": 30
20
- }.freeze
21
-
22
- def self.priorities
23
- PRIORITIES
24
- end
25
- end
26
- end
27
- end