keisan 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7bc1aae204b2b2e112ca0c8f2567023684ddbec83cd1c5c4c1a354cf27eb75b
4
- data.tar.gz: 6353f1b48be09dbbef2cf30167b9fe2d0ac9400fb728def8c75a2241294196e6
3
+ metadata.gz: d539ead6f33b2151b228dfe6c30a0e3f7d40bb7b1113c90b851d020e04106df5
4
+ data.tar.gz: c36af3538e6f448c285b9857aa5ea14e3bc90853e5d3f4a74fd726d8b0c35068
5
5
  SHA512:
6
- metadata.gz: 8fa93fed5b5fd0e55c0330e017e1628b3a3c4dc2b9fcdb2dbbf521b6e7149c9f2ee44544cb1f3cdbc84d09d171fb794f4d6a3a22997b5d8728607ea07542d3ee
7
- data.tar.gz: 471b9f1378dab5e0dae5556ed693e00bd73c2e841f463486b5f7e013867dd1f05b52e675c381607b5f564d84ee0cfd1a4c69a49805f338d7823798bed7f94bff
6
+ metadata.gz: 67557029c43754d862406fc0491594b94dcc4dac5a925e518232accfd75c42582f8e5d11b5f99eec7f44dcb1ea29ea31f087668bf70a68c56fa25fc4ca8f2929
7
+ data.tar.gz: 2451bd2dbe844af1bc3a4f2ec9d0819aeb4df52f96bd45dbbc5ada1993b2c6003245c8f6191ce3f5dc59de18b106f313e07dedd3aef9ba670525d4bacabfb43a
@@ -17,8 +17,8 @@ module Keisan
17
17
  child.unbound_functions(local)
18
18
  end
19
19
 
20
- def contains_a?(klass)
21
- super || child.contains_a?(klass)
20
+ def traverse(&block)
21
+ super(&block) || child.traverse(&block)
22
22
  end
23
23
 
24
24
  def deep_dup
@@ -15,8 +15,8 @@ module Keisan
15
15
  node.unbound_functions(context)
16
16
  end
17
17
 
18
- def contains_a?(klass)
19
- super || node.contains_a?(klass)
18
+ def traverse(&block)
19
+ super(&block) || node.traverse(&block)
20
20
  end
21
21
 
22
22
  def deep_dup
@@ -21,8 +21,16 @@ module Keisan
21
21
  end
22
22
  end
23
23
 
24
- def contains_a?(klass)
25
- super || @hash.any? {|k, v| k.to_node.contains_a?(klass) || v.contains_a?(klass) }
24
+ def traverse(&block)
25
+ value = super(&block)
26
+ return value if value
27
+ @hash.each do |k, v|
28
+ value = k.to_node.traverse(&block)
29
+ return value if value
30
+ value = v.traverse(&block)
31
+ return value if value
32
+ end
33
+ false
26
34
  end
27
35
 
28
36
  def evaluate(context = nil)
@@ -37,12 +37,26 @@ module Keisan
37
37
  value(context)
38
38
  end
39
39
 
40
+ # Takes a block, and does a DFS down the AST, evaluating the received block
41
+ # at each node, passing in the node as the single argument. If the block
42
+ # returns a truthy value at any point, the DFS ends and the return value is
43
+ # percolated up the tree.
44
+ def traverse(&block)
45
+ block.call(self)
46
+ end
47
+
40
48
  def contains_a?(klass)
41
49
  case klass
42
50
  when Array
43
- klass.any? {|k| is_a?(k) }
51
+ klass.any? do |k|
52
+ traverse do |node|
53
+ node.is_a?(k)
54
+ end
55
+ end
44
56
  else
45
- is_a?(klass)
57
+ traverse do |node|
58
+ node.is_a?(klass)
59
+ end
46
60
  end
47
61
  end
48
62
 
@@ -25,8 +25,14 @@ module Keisan
25
25
  end
26
26
  end
27
27
 
28
- def contains_a?(klass)
29
- super || children.any? {|child| child.contains_a?(klass) }
28
+ def traverse(&block)
29
+ value = super(&block)
30
+ return value if value
31
+ children.each do |child|
32
+ value = child.traverse(&block)
33
+ return value if value
34
+ end
35
+ false
30
36
  end
31
37
 
32
38
  def freeze
@@ -4,11 +4,12 @@ module Keisan
4
4
 
5
5
  # Note, allow_recursive would be more appropriately named:
6
6
  # allow_unbound_functions_in_function_definitions, but it is too late for that.
7
- def initialize(context: nil, allow_recursive: false, allow_blocks: true, allow_multiline: true)
7
+ def initialize(context: nil, allow_recursive: false, allow_blocks: true, allow_multiline: true, allow_random: true)
8
8
  @context = context || Context.new(
9
9
  allow_recursive: allow_recursive,
10
10
  allow_blocks: allow_blocks,
11
- allow_multiline: allow_multiline
11
+ allow_multiline: allow_multiline,
12
+ allow_random: allow_random
12
13
  )
13
14
  end
14
15
 
@@ -28,6 +29,10 @@ module Keisan
28
29
  context.allow_multiline
29
30
  end
30
31
 
32
+ def allow_random
33
+ context.allow_random
34
+ end
35
+
31
36
  def evaluate(expression, definitions = {})
32
37
  Evaluator.new(self).evaluate(expression, definitions)
33
38
  end
@@ -4,13 +4,15 @@ module Keisan
4
4
  :variable_registry,
5
5
  :allow_recursive,
6
6
  :allow_multiline,
7
- :allow_blocks
7
+ :allow_blocks,
8
+ :allow_random
8
9
 
9
10
  def initialize(parent: nil,
10
11
  random: nil,
11
12
  allow_recursive: false,
12
13
  allow_multiline: true,
13
14
  allow_blocks: true,
15
+ allow_random: true,
14
16
  shadowed: [])
15
17
  @parent = parent
16
18
  @function_registry = Functions::Registry.new(parent: @parent&.function_registry)
@@ -19,6 +21,7 @@ module Keisan
19
21
  @allow_recursive = allow_recursive
20
22
  @allow_multiline = allow_multiline
21
23
  @allow_blocks = allow_blocks
24
+ @allow_random = allow_random
22
25
  end
23
26
 
24
27
  def allow_recursive!
@@ -111,10 +114,12 @@ module Keisan
111
114
  end
112
115
 
113
116
  def random
117
+ raise Keisan::Exceptions::InvalidExpression.new("Context does not permit expressions with randomness") unless allow_random
114
118
  @random ||= @parent&.random || Random.new
115
119
  end
116
120
 
117
121
  def set_random(random)
122
+ raise Keisan::Exceptions::InvalidExpression.new("Context does not permit expressions with randomness") unless allow_random
118
123
  @random = random
119
124
  end
120
125
 
@@ -1,3 +1,3 @@
1
1
  module Keisan
2
- VERSION = "0.8.7"
2
+ VERSION = "0.8.8"
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.8.7
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Locke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-29 00:00:00.000000000 Z
11
+ date: 2021-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmath