keisan 0.8.12 → 0.8.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39ac1f6356b788327b43e6819d18b136da5bbada5f410b64c3f6995b2877973b
4
- data.tar.gz: 60522376948b4806c0e45cb4f8e09e5187d37448fae0831630fea1f07608485c
3
+ metadata.gz: '05596336b8e5f1de3f7787b6a36120152f4e13c8caa822da225fe989f6af3c72'
4
+ data.tar.gz: 9a4d79fbc8ed709ec7d0f9b90d0e31f4f3e65c7e43b067800b66a0ea7c568ffb
5
5
  SHA512:
6
- metadata.gz: 964905af3a5734456ea5e3f81ddb5183a7512e9cf81567c72586dbab813123160d4aaa085467f2626bd0e29df861f87e44425e216b8ccf174cb9f1251d578122
7
- data.tar.gz: be653ccfd93f2fa6ce3a33e26be4e14db33e9ccea8d2273d491e8df0aaa16b400291b08e90d66cd48020efc691742bf49667b3547fcae57e8adeaab52bf18d5d
6
+ metadata.gz: d040a4d12325c74a8775d7a87a7d450fd0218de3e639b7ac43fe53bbb1310000cd53207e98727266f59535c5f7347d74392b941b66ad10359d97c515d5e02f75
7
+ data.tar.gz: 81ce4fe88b6d215a194bd8cf45388957689353c275cb8e60ec921a26eac8cb86d10c067ed34e09f6f303482f2b913005bc07c3448aed413d291b3beb66ecbf4f
@@ -66,7 +66,7 @@ module Keisan
66
66
  end
67
67
 
68
68
  def to_cell
69
- self.class.new(node.to_cell)
69
+ self.class.new(node.to_node)
70
70
  end
71
71
 
72
72
  def to_s
@@ -26,7 +26,7 @@ module Keisan
26
26
 
27
27
  def short_circuit_do(method, context)
28
28
  context ||= Context.new
29
- lhs = children[0].send(method, context)
29
+ lhs = children[0].send(method, context).to_node
30
30
  case lhs
31
31
  when AST::Boolean
32
32
  lhs.false? ? AST::Boolean.new(false) : children[1].send(method, context)
@@ -26,7 +26,7 @@ module Keisan
26
26
 
27
27
  def short_circuit_do(method, context)
28
28
  context ||= Context.new
29
- lhs = children[0].send(method, context)
29
+ lhs = children[0].send(method, context).to_node
30
30
  case lhs
31
31
  when AST::Boolean
32
32
  lhs.true? ? AST::Boolean.new(true) : children[1].send(method, context)
@@ -29,7 +29,7 @@ module Keisan
29
29
  AST::List.new(
30
30
  list.children.select do |element|
31
31
  local.register_variable!(variable, element)
32
- result = expression.evaluated(local)
32
+ result = expression.evaluated(local).to_node
33
33
 
34
34
  case result
35
35
  when AST::Boolean
@@ -54,7 +54,7 @@ module Keisan
54
54
  hash.select do |cur_key, cur_value|
55
55
  local.register_variable!(key, cur_key)
56
56
  local.register_variable!(value, cur_value)
57
- result = expression.evaluated(local)
57
+ result = expression.evaluated(local).to_node
58
58
 
59
59
  case result
60
60
  when AST::Boolean
@@ -13,12 +13,13 @@ module Keisan
13
13
  def evaluate(ast_function, context = nil)
14
14
  validate_arguments!(ast_function.children.count)
15
15
  context ||= Context.new
16
-
17
- bool = ast_function.children[0].evaluate(context)
16
+ bool = ast_function.children[0].evaluate(context).to_node
18
17
 
19
18
  if bool.is_a?(AST::Boolean)
20
19
  node = bool.value ? ast_function.children[1] : ast_function.children[2]
21
20
  node.to_node.evaluate(context)
21
+ elsif bool.is_constant?
22
+ raise Keisan::Exceptions::InvalidFunctionError.new("if statement must work on booleans, other constants are not supported")
22
23
  else
23
24
  ast_function
24
25
  end
@@ -27,7 +28,7 @@ module Keisan
27
28
  def simplify(ast_function, context = nil)
28
29
  validate_arguments!(ast_function.children.count)
29
30
  context ||= Context.new
30
- bool = ast_function.children[0].simplify(context)
31
+ bool = ast_function.children[0].simplify(context).to_node
31
32
 
32
33
  if bool.is_a?(AST::Boolean)
33
34
  if bool.value
@@ -37,6 +38,8 @@ module Keisan
37
38
  else
38
39
  Keisan::AST::Null.new
39
40
  end
41
+ elsif bool.is_constant?
42
+ raise Keisan::Exceptions::InvalidFunctionError.new("if statement must work on booleans, other constants are not supported")
40
43
  else
41
44
  ast_function
42
45
  end
@@ -1,6 +1,9 @@
1
1
  module Keisan
2
2
  module Functions
3
3
  class While < Keisan::Function
4
+ class WhileLogicalNodeIsNotConstant < Keisan::Exceptions::StandardError; end
5
+ class WhileLogicalNodeIsNonBoolConstant < Keisan::Exceptions::StandardError; end
6
+
4
7
  def initialize
5
8
  super("while", 2)
6
9
  end
@@ -13,27 +16,43 @@ module Keisan
13
16
  def evaluate(ast_function, context = nil)
14
17
  validate_arguments!(ast_function.children.count)
15
18
  context ||= Keisan::Context.new
16
- simplify(ast_function, context)
19
+ while_loop(ast_function, context, simplify: false)
17
20
  end
18
21
 
19
22
  def simplify(ast_function, context = nil)
20
23
  validate_arguments!(ast_function.children.count)
21
24
  context ||= Context.new
22
- while_loop(ast_function.children[0], ast_function.children[1], context)
25
+ while_loop(ast_function, context, simplify: true)
23
26
  end
24
27
 
25
28
  private
26
29
 
27
- def while_loop(logical_node, body_node, context)
30
+ def while_loop(ast_function, context, simplify: true)
31
+ logical_node, body_node = ast_function.children[0], ast_function.children[1]
28
32
  current = Keisan::AST::Null.new
29
33
 
30
- while logical_node_evaluates_to_true(logical_node, context)
31
- begin
32
- current = body_node.evaluated(context)
33
- rescue Exceptions::BreakError
34
- break
35
- rescue Exceptions::ContinueError
36
- next
34
+ begin
35
+ while logical_node_evaluates_to_true(logical_node, context)
36
+ begin
37
+ current = body_node.evaluated(context)
38
+ rescue Exceptions::BreakError
39
+ break
40
+ rescue Exceptions::ContinueError
41
+ next
42
+ end
43
+ end
44
+
45
+ # While loops should work on booleans, not other types of constants
46
+ rescue WhileLogicalNodeIsNonBoolConstant
47
+ raise Keisan::Exceptions::InvalidFunctionError.new("while condition must evaluate to a boolean")
48
+
49
+ # If the logical expression is not constant (e.g. boolean), then we
50
+ # cannot simplify the while loop, and an evaluate should raise an error.
51
+ rescue WhileLogicalNodeIsNotConstant
52
+ if simplify
53
+ return ast_function
54
+ else
55
+ raise Keisan::Exceptions::InvalidFunctionError.new("while condition must evaluate to a boolean")
37
56
  end
38
57
  end
39
58
 
@@ -41,11 +60,15 @@ module Keisan
41
60
  end
42
61
 
43
62
  def logical_node_evaluates_to_true(logical_node, context)
44
- bool = logical_node.evaluated(context)
45
- unless bool.is_a?(AST::Boolean)
46
- raise Keisan::Exceptions::InvalidFunctionError.new("while condition must evaluate to a boolean")
63
+ bool = logical_node.evaluated(context).to_node
64
+
65
+ if bool.is_a?(AST::Boolean)
66
+ bool.value(context)
67
+ elsif bool.is_constant?
68
+ raise WhileLogicalNodeIsNonBoolConstant.new
69
+ else
70
+ raise WhileLogicalNodeIsNotConstant.new
47
71
  end
48
- bool.value(context)
49
72
  end
50
73
  end
51
74
  end
@@ -1,3 +1,3 @@
1
1
  module Keisan
2
- VERSION = "0.8.12"
2
+ VERSION = "0.8.13"
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.12
4
+ version: 0.8.13
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-05-20 00:00:00.000000000 Z
11
+ date: 2021-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmath