keisan 0.3.0 → 0.4.0

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