keisan 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -1
- data/keisan.gemspec +1 -0
- data/lib/keisan.rb +30 -0
- data/lib/keisan/ast/assignment.rb +44 -17
- data/lib/keisan/ast/block.rb +60 -0
- data/lib/keisan/ast/boolean.rb +5 -5
- data/lib/keisan/ast/builder.rb +10 -207
- data/lib/keisan/ast/cell.rb +60 -0
- data/lib/keisan/ast/constant_literal.rb +9 -0
- data/lib/keisan/ast/exponent.rb +6 -6
- data/lib/keisan/ast/function.rb +12 -8
- data/lib/keisan/ast/indexing.rb +25 -15
- data/lib/keisan/ast/line_builder.rb +230 -0
- data/lib/keisan/ast/list.rb +28 -1
- data/lib/keisan/ast/literal.rb +0 -8
- data/lib/keisan/ast/logical_and.rb +1 -1
- data/lib/keisan/ast/logical_or.rb +1 -1
- data/lib/keisan/ast/multi_line.rb +28 -0
- data/lib/keisan/ast/node.rb +32 -24
- data/lib/keisan/ast/number.rb +31 -31
- data/lib/keisan/ast/operator.rb +12 -4
- data/lib/keisan/ast/parent.rb +4 -4
- data/lib/keisan/ast/plus.rb +10 -10
- data/lib/keisan/ast/string.rb +3 -3
- data/lib/keisan/ast/times.rb +8 -8
- data/lib/keisan/ast/unary_identity.rb +1 -1
- data/lib/keisan/ast/unary_inverse.rb +7 -7
- data/lib/keisan/ast/unary_minus.rb +5 -5
- data/lib/keisan/ast/unary_operator.rb +2 -2
- data/lib/keisan/ast/unary_plus.rb +2 -2
- data/lib/keisan/ast/variable.rb +26 -10
- data/lib/keisan/context.rb +5 -5
- data/lib/keisan/evaluator.rb +15 -8
- data/lib/keisan/function.rb +24 -6
- data/lib/keisan/functions/cbrt.rb +1 -1
- data/lib/keisan/functions/cos.rb +1 -1
- data/lib/keisan/functions/cosh.rb +1 -1
- data/lib/keisan/functions/cot.rb +1 -1
- data/lib/keisan/functions/coth.rb +1 -1
- data/lib/keisan/functions/csc.rb +1 -1
- data/lib/keisan/functions/csch.rb +1 -1
- data/lib/keisan/functions/default_registry.rb +53 -74
- data/lib/keisan/functions/diff.rb +18 -14
- data/lib/keisan/functions/erf.rb +15 -0
- data/lib/keisan/functions/exp.rb +1 -1
- data/lib/keisan/functions/expression_function.rb +15 -21
- data/lib/keisan/functions/filter.rb +13 -15
- data/lib/keisan/functions/if.rb +14 -20
- data/lib/keisan/functions/let.rb +36 -0
- data/lib/keisan/functions/map.rb +11 -13
- data/lib/keisan/functions/math_function.rb +2 -2
- data/lib/keisan/functions/proc_function.rb +10 -6
- data/lib/keisan/functions/rand.rb +2 -1
- data/lib/keisan/functions/range.rb +74 -0
- data/lib/keisan/functions/reduce.rb +12 -14
- data/lib/keisan/functions/registry.rb +7 -7
- data/lib/keisan/functions/replace.rb +8 -8
- data/lib/keisan/functions/sample.rb +2 -1
- data/lib/keisan/functions/sec.rb +1 -1
- data/lib/keisan/functions/sech.rb +1 -1
- data/lib/keisan/functions/sin.rb +1 -1
- data/lib/keisan/functions/sinh.rb +1 -1
- data/lib/keisan/functions/sqrt.rb +1 -1
- data/lib/keisan/functions/tan.rb +1 -1
- data/lib/keisan/functions/tanh.rb +1 -1
- data/lib/keisan/functions/while.rb +46 -0
- data/lib/keisan/parser.rb +121 -79
- data/lib/keisan/parsing/assignment.rb +1 -1
- data/lib/keisan/parsing/bitwise_and.rb +1 -1
- data/lib/keisan/parsing/bitwise_not.rb +1 -1
- data/lib/keisan/parsing/bitwise_not_not.rb +1 -1
- data/lib/keisan/parsing/bitwise_or.rb +1 -1
- data/lib/keisan/parsing/bitwise_xor.rb +1 -1
- data/lib/keisan/parsing/curly_group.rb +6 -0
- data/lib/keisan/parsing/divide.rb +1 -1
- data/lib/keisan/parsing/exponent.rb +1 -1
- data/lib/keisan/parsing/function.rb +1 -1
- data/lib/keisan/parsing/group.rb +1 -1
- data/lib/keisan/parsing/indexing.rb +1 -1
- data/lib/keisan/parsing/line_separator.rb +6 -0
- data/lib/keisan/parsing/logical_and.rb +1 -1
- data/lib/keisan/parsing/logical_equal.rb +1 -1
- data/lib/keisan/parsing/logical_greater_than.rb +1 -1
- data/lib/keisan/parsing/logical_greater_than_or_equal_to.rb +1 -1
- data/lib/keisan/parsing/logical_less_than.rb +1 -1
- data/lib/keisan/parsing/logical_less_than_or_equal_to.rb +1 -1
- data/lib/keisan/parsing/logical_not.rb +1 -1
- data/lib/keisan/parsing/logical_not_equal.rb +1 -1
- data/lib/keisan/parsing/logical_not_not.rb +1 -1
- data/lib/keisan/parsing/logical_or.rb +1 -1
- data/lib/keisan/parsing/minus.rb +1 -1
- data/lib/keisan/parsing/modulo.rb +1 -1
- data/lib/keisan/parsing/operator.rb +1 -1
- data/lib/keisan/parsing/plus.rb +1 -1
- data/lib/keisan/parsing/times.rb +1 -1
- data/lib/keisan/parsing/unary_minus.rb +1 -1
- data/lib/keisan/parsing/unary_operator.rb +1 -1
- data/lib/keisan/parsing/unary_plus.rb +1 -1
- data/lib/keisan/repl.rb +1 -1
- data/lib/keisan/tokenizer.rb +4 -9
- data/lib/keisan/tokens/group.rb +3 -1
- data/lib/keisan/tokens/line_separator.rb +11 -0
- data/lib/keisan/variables/default_registry.rb +0 -5
- data/lib/keisan/variables/registry.rb +7 -7
- data/lib/keisan/version.rb +1 -1
- metadata +27 -2
data/lib/keisan/ast/list.rb
CHANGED
@@ -1,14 +1,41 @@
|
|
1
1
|
module Keisan
|
2
2
|
module AST
|
3
3
|
class List < Parent
|
4
|
+
def initialize(children = [])
|
5
|
+
super(children)
|
6
|
+
cellify!
|
7
|
+
end
|
8
|
+
|
9
|
+
def evaluate(context = nil)
|
10
|
+
context ||= Context.new
|
11
|
+
super(context)
|
12
|
+
cellify!
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def simplify(context = nil)
|
17
|
+
context ||= Context.new
|
18
|
+
super(context)
|
19
|
+
cellify!
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
4
23
|
def value(context = nil)
|
5
|
-
context ||=
|
24
|
+
context ||= Context.new
|
6
25
|
children.map {|child| child.value(context)}
|
7
26
|
end
|
8
27
|
|
9
28
|
def to_s
|
10
29
|
"[#{children.map(&:to_s).join(',')}]"
|
11
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def cellify!
|
35
|
+
@children = @children.map do |child|
|
36
|
+
child.is_a?(Cell) ? child : Cell.new(child)
|
37
|
+
end
|
38
|
+
end
|
12
39
|
end
|
13
40
|
end
|
14
41
|
end
|
data/lib/keisan/ast/literal.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Keisan
|
2
|
+
module AST
|
3
|
+
class MultiLine < Parent
|
4
|
+
def value(context = nil)
|
5
|
+
context ||= Context.new
|
6
|
+
evaluate(context).value(context)
|
7
|
+
end
|
8
|
+
|
9
|
+
def evaluate_assignments(context = nil)
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate(context = nil)
|
14
|
+
context ||= Context.new
|
15
|
+
@children = children.map {|child| child.evaluate(context)}
|
16
|
+
@children.last
|
17
|
+
end
|
18
|
+
|
19
|
+
def simplify(context = nil)
|
20
|
+
evaluate(context)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
children.map(&:to_s).join(";")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/keisan/ast/node.rb
CHANGED
@@ -2,7 +2,7 @@ module Keisan
|
|
2
2
|
module AST
|
3
3
|
class Node
|
4
4
|
def value(context = nil)
|
5
|
-
raise
|
5
|
+
raise Exceptions::NotImplementedError.new
|
6
6
|
end
|
7
7
|
|
8
8
|
def unbound_variables(context = nil)
|
@@ -29,12 +29,20 @@ module Keisan
|
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
32
|
+
def evaluated(context = nil)
|
33
|
+
deep_dup.evaluate(context)
|
34
|
+
end
|
35
|
+
|
32
36
|
def evaluate(context = nil)
|
37
|
+
value(context)
|
38
|
+
end
|
39
|
+
|
40
|
+
def evaluate_assignments(context = nil)
|
33
41
|
self
|
34
42
|
end
|
35
43
|
|
36
44
|
def differentiate(variable, context = nil)
|
37
|
-
raise
|
45
|
+
raise Exceptions::NonDifferentiableError.new
|
38
46
|
end
|
39
47
|
|
40
48
|
def replace(variable, replacement)
|
@@ -50,41 +58,41 @@ module Keisan
|
|
50
58
|
end
|
51
59
|
|
52
60
|
def +(other)
|
53
|
-
|
61
|
+
Plus.new(
|
54
62
|
[self, other.to_node]
|
55
63
|
)
|
56
64
|
end
|
57
65
|
|
58
66
|
def -(other)
|
59
|
-
|
60
|
-
[self,
|
67
|
+
Plus.new(
|
68
|
+
[self, UnaryMinus.new(other.to_node)]
|
61
69
|
)
|
62
70
|
end
|
63
71
|
|
64
72
|
def *(other)
|
65
|
-
|
73
|
+
Times.new(
|
66
74
|
[self, other.to_node]
|
67
75
|
)
|
68
76
|
end
|
69
77
|
|
70
78
|
def /(other)
|
71
|
-
|
72
|
-
[self,
|
79
|
+
Times.new(
|
80
|
+
[self, UnaryInverse.new(other.to_node)]
|
73
81
|
)
|
74
82
|
end
|
75
83
|
|
76
84
|
def %(other)
|
77
|
-
|
85
|
+
Modulo.new(
|
78
86
|
[self, other.to_node]
|
79
87
|
)
|
80
88
|
end
|
81
89
|
|
82
90
|
def !
|
83
|
-
|
91
|
+
UnaryLogicalNot.new(self)
|
84
92
|
end
|
85
93
|
|
86
94
|
def ~
|
87
|
-
|
95
|
+
UnaryBitwiseNot.new(self)
|
88
96
|
end
|
89
97
|
|
90
98
|
def +@
|
@@ -92,55 +100,55 @@ module Keisan
|
|
92
100
|
end
|
93
101
|
|
94
102
|
def -@
|
95
|
-
|
103
|
+
UnaryMinus.new(self)
|
96
104
|
end
|
97
105
|
|
98
106
|
def **(other)
|
99
|
-
|
107
|
+
Exponent.new([self, other.to_node])
|
100
108
|
end
|
101
109
|
|
102
110
|
def &(other)
|
103
|
-
|
111
|
+
BitwiseAnd.new([self, other.to_node])
|
104
112
|
end
|
105
113
|
|
106
114
|
def ^(other)
|
107
|
-
|
115
|
+
BitwiseXor.new([self, other.to_node])
|
108
116
|
end
|
109
117
|
|
110
118
|
def |(other)
|
111
|
-
|
119
|
+
BitwiseOr.new([self, other.to_node])
|
112
120
|
end
|
113
121
|
|
114
122
|
def >(other)
|
115
|
-
|
123
|
+
LogicalGreaterThan.new([self, other.to_node])
|
116
124
|
end
|
117
125
|
|
118
126
|
def >=(other)
|
119
|
-
|
127
|
+
LogicalGreaterThanOrEqualTo.new([self, other.to_node])
|
120
128
|
end
|
121
129
|
|
122
130
|
def <(other)
|
123
|
-
|
131
|
+
LogicalLessThan.new([self, other.to_node])
|
124
132
|
end
|
125
133
|
|
126
134
|
def <=(other)
|
127
|
-
|
135
|
+
LogicalLessThanOrEqualTo.new([self, other.to_node])
|
128
136
|
end
|
129
137
|
|
130
138
|
def equal(other)
|
131
|
-
|
139
|
+
LogicalEqual.new([self, other.to_node])
|
132
140
|
end
|
133
141
|
|
134
142
|
def not_equal(other)
|
135
|
-
|
143
|
+
LogicalNotEqual.new([self, other.to_node])
|
136
144
|
end
|
137
145
|
|
138
146
|
def and(other)
|
139
|
-
|
147
|
+
LogicalAnd.new([self, other.to_node])
|
140
148
|
end
|
141
149
|
|
142
150
|
def or(other)
|
143
|
-
|
151
|
+
LogicalOr.new([self, other.to_node])
|
144
152
|
end
|
145
153
|
end
|
146
154
|
end
|
data/lib/keisan/ast/number.rb
CHANGED
@@ -12,18 +12,18 @@ module Keisan
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def -@
|
15
|
-
|
15
|
+
Number.new(-value)
|
16
16
|
end
|
17
17
|
|
18
18
|
def +@
|
19
|
-
|
19
|
+
Number.new(value)
|
20
20
|
end
|
21
21
|
|
22
22
|
def +(other)
|
23
23
|
other = other.to_node
|
24
24
|
case other
|
25
|
-
when
|
26
|
-
|
25
|
+
when Number
|
26
|
+
Number.new(value + other.value)
|
27
27
|
else
|
28
28
|
super
|
29
29
|
end
|
@@ -36,8 +36,8 @@ module Keisan
|
|
36
36
|
def *(other)
|
37
37
|
other = other.to_node
|
38
38
|
case other
|
39
|
-
when
|
40
|
-
|
39
|
+
when Number
|
40
|
+
Number.new(value * other.value)
|
41
41
|
else
|
42
42
|
super
|
43
43
|
end
|
@@ -46,8 +46,8 @@ module Keisan
|
|
46
46
|
def /(other)
|
47
47
|
other = other.to_node
|
48
48
|
case other
|
49
|
-
when
|
50
|
-
|
49
|
+
when Number
|
50
|
+
Number.new(Rational(value, other.value))
|
51
51
|
else
|
52
52
|
super
|
53
53
|
end
|
@@ -56,8 +56,8 @@ module Keisan
|
|
56
56
|
def **(other)
|
57
57
|
other = other.to_node
|
58
58
|
case other
|
59
|
-
when
|
60
|
-
|
59
|
+
when Number
|
60
|
+
Number.new(value ** other.value)
|
61
61
|
else
|
62
62
|
super
|
63
63
|
end
|
@@ -66,8 +66,8 @@ module Keisan
|
|
66
66
|
def %(other)
|
67
67
|
other = other.to_node
|
68
68
|
case other
|
69
|
-
when
|
70
|
-
|
69
|
+
when Number
|
70
|
+
Number.new(value % other.value)
|
71
71
|
else
|
72
72
|
super
|
73
73
|
end
|
@@ -76,22 +76,22 @@ module Keisan
|
|
76
76
|
def &(other)
|
77
77
|
other = other.to_node
|
78
78
|
case other
|
79
|
-
when
|
80
|
-
|
79
|
+
when Number
|
80
|
+
Number.new(value & other.value)
|
81
81
|
else
|
82
82
|
super
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
def ~
|
87
|
-
|
87
|
+
Number.new(~value)
|
88
88
|
end
|
89
89
|
|
90
90
|
def ^(other)
|
91
91
|
other = other.to_node
|
92
92
|
case other
|
93
|
-
when
|
94
|
-
|
93
|
+
when Number
|
94
|
+
Number.new(value ^ other.value)
|
95
95
|
else
|
96
96
|
super
|
97
97
|
end
|
@@ -100,8 +100,8 @@ module Keisan
|
|
100
100
|
def |(other)
|
101
101
|
other = other.to_node
|
102
102
|
case other
|
103
|
-
when
|
104
|
-
|
103
|
+
when Number
|
104
|
+
Number.new(value | other.value)
|
105
105
|
else
|
106
106
|
super
|
107
107
|
end
|
@@ -110,8 +110,8 @@ module Keisan
|
|
110
110
|
def >(other)
|
111
111
|
other = other.to_node
|
112
112
|
case other
|
113
|
-
when
|
114
|
-
|
113
|
+
when Number
|
114
|
+
Boolean.new(value > other.value)
|
115
115
|
else
|
116
116
|
super
|
117
117
|
end
|
@@ -120,8 +120,8 @@ module Keisan
|
|
120
120
|
def >=(other)
|
121
121
|
other = other.to_node
|
122
122
|
case other
|
123
|
-
when
|
124
|
-
|
123
|
+
when Number
|
124
|
+
Boolean.new(value >= other.value)
|
125
125
|
else
|
126
126
|
super
|
127
127
|
end
|
@@ -130,8 +130,8 @@ module Keisan
|
|
130
130
|
def <(other)
|
131
131
|
other = other.to_node
|
132
132
|
case other
|
133
|
-
when
|
134
|
-
|
133
|
+
when Number
|
134
|
+
Boolean.new(value < other.value)
|
135
135
|
else
|
136
136
|
super
|
137
137
|
end
|
@@ -140,8 +140,8 @@ module Keisan
|
|
140
140
|
def <=(other)
|
141
141
|
other = other.to_node
|
142
142
|
case other
|
143
|
-
when
|
144
|
-
|
143
|
+
when Number
|
144
|
+
Boolean.new(value <= other.value)
|
145
145
|
else
|
146
146
|
super
|
147
147
|
end
|
@@ -150,8 +150,8 @@ module Keisan
|
|
150
150
|
def equal(other)
|
151
151
|
other = other.to_node
|
152
152
|
case other
|
153
|
-
when
|
154
|
-
|
153
|
+
when Number
|
154
|
+
Boolean.new(value == other.value)
|
155
155
|
else
|
156
156
|
super
|
157
157
|
end
|
@@ -160,8 +160,8 @@ module Keisan
|
|
160
160
|
def not_equal(other)
|
161
161
|
other = other.to_node
|
162
162
|
case other
|
163
|
-
when
|
164
|
-
|
163
|
+
when Number
|
164
|
+
Boolean.new(value != other.value)
|
165
165
|
else
|
166
166
|
super
|
167
167
|
end
|
data/lib/keisan/ast/operator.rb
CHANGED
@@ -38,7 +38,7 @@ module Keisan
|
|
38
38
|
|
39
39
|
def initialize(children = [], parsing_operators = [])
|
40
40
|
unless parsing_operators.empty? || children.count == parsing_operators.count + 1
|
41
|
-
raise
|
41
|
+
raise Exceptions::ASTError.new("Mismatch of children and operators")
|
42
42
|
end
|
43
43
|
|
44
44
|
children = Array.wrap(children)
|
@@ -47,6 +47,14 @@ module Keisan
|
|
47
47
|
@parsing_operators = parsing_operators
|
48
48
|
end
|
49
49
|
|
50
|
+
def evaluate_assignments(context = nil)
|
51
|
+
context ||= Context.new
|
52
|
+
@children = children.map do |child|
|
53
|
+
child.evaluate_assignments(context)
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
50
58
|
def self.associativity_of_priority(priority)
|
51
59
|
ASSOCIATIVITY_OF_PRIORITY[priority]
|
52
60
|
end
|
@@ -80,11 +88,11 @@ module Keisan
|
|
80
88
|
end
|
81
89
|
|
82
90
|
def self.symbol
|
83
|
-
raise
|
91
|
+
raise Exceptions::NotImplementedError.new
|
84
92
|
end
|
85
93
|
|
86
94
|
def blank_value
|
87
|
-
raise
|
95
|
+
raise Exceptions::NotImplementedError.new
|
88
96
|
end
|
89
97
|
|
90
98
|
def value(context = nil)
|
@@ -103,7 +111,7 @@ module Keisan
|
|
103
111
|
def to_s
|
104
112
|
children.map do |child|
|
105
113
|
case child
|
106
|
-
when
|
114
|
+
when Operator
|
107
115
|
"(#{child.to_s})"
|
108
116
|
else
|
109
117
|
"#{child.to_s}"
|