keisan 0.8.12 → 0.8.13

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: 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