skeem 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -3
- data/README.md +3 -3
- data/lib/skeem/primitive/primitive_builder.rb +59 -4
- data/lib/skeem/s_expr_nodes.rb +17 -13
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/interpreter_spec.rb +30 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e19432168939085384bceaf28be0364177ddf91b
|
4
|
+
data.tar.gz: 1256c3c464d7edb6fcf7d3cf6c1d1fd1bd2446ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7817ca715480e6d21c46ba46da12bb6652592f258348968dc3e3c705c717542ddca63b63493758ba2a470e300a5d1263b61762ae21746fc81afede599eae36e7
|
7
|
+
data.tar.gz: 948438de92a59ada9b5589a312df5c71fbd9e884328a6b4c8ad1422578ae0471dbdb170354499a4fa5cd7811809ca38f97785ec183b5c820edce1121b770a656
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
|
+
## [0.0.8] - 2018-09-13
|
2
|
+
Added primitive operators: '-', '*', '/' operators.
|
3
|
+
|
4
|
+
### Added
|
5
|
+
- Class `PrimitiveBuilder`. Added methods to implement the arithmetic operators - (subtraction), * (product), / (division)
|
6
|
+
- Class `SExprList`. Class refactoring
|
7
|
+
- Class `PrimitiveFunc` Internal representation of primitive functions.
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- File `interpreter_spec.rb` Added tests for arithmetic expressions.
|
11
|
+
- File `README.md` Changed demo snippet with example of arithmetic expression.
|
12
|
+
|
1
13
|
## [0.0.7] - 2018-09-12
|
2
|
-
Proof of concept of a primitive function: '+' operator.
|
3
|
-
Demo works but code needs some polishing and testing.
|
14
|
+
Proof of concept of a primitive function: '+' operator.
|
15
|
+
Demo works but code needs some polishing and testing.
|
4
16
|
|
5
17
|
### Added
|
6
18
|
- Class `Environment`. Holds a mapping between symbol names and their associated value.
|
@@ -62,7 +74,7 @@ Parser now generates correct parse trees for expressions consisting of a single
|
|
62
74
|
|
63
75
|
## [0.0.0] - 2018-08-24
|
64
76
|
### Added
|
65
|
-
- Initial Github commit
|
77
|
+
- Initial Github commit
|
66
78
|
|
67
79
|
## Unreleased
|
68
80
|
### Added
|
data/README.md
CHANGED
@@ -32,11 +32,11 @@ At this stage, the gem consists of a bare-bones interpreter.
|
|
32
32
|
|
33
33
|
schemer = Skeem::Interpreter.new
|
34
34
|
scheme_code =<<-SKEEM
|
35
|
-
; Let's try
|
36
|
-
(+
|
35
|
+
; Let's try some arithmetic expression
|
36
|
+
(+ (* 2 100) (* 1 10))
|
37
37
|
SKEEM
|
38
38
|
result = schemer.run(scheme_code)
|
39
|
-
puts result.value # =>
|
39
|
+
puts result.value # => 210
|
40
40
|
```
|
41
41
|
|
42
42
|
Roadmap:
|
@@ -11,20 +11,75 @@ module Skeem
|
|
11
11
|
|
12
12
|
def add_arithmetic(aRuntime)
|
13
13
|
def_func(aRuntime, create_plus)
|
14
|
+
def_func(aRuntime, create_minus)
|
15
|
+
def_func(aRuntime, create_multiply)
|
16
|
+
def_func(aRuntime, create_divide)
|
14
17
|
end
|
15
18
|
|
16
19
|
def create_plus()
|
17
20
|
plus_code = ->(runtime, arglist) do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
first_one = arglist.head.evaluate(runtime)
|
22
|
+
operands = arglist.tail.to_eval_enum(runtime)
|
23
|
+
raw_result = first_one.value
|
24
|
+
operands.each { |elem| raw_result += elem.value }
|
25
|
+
if raw_result.kind_of?(Float)
|
26
|
+
SExprReal.create(raw_result)
|
27
|
+
else
|
28
|
+
SExprInteger.create(raw_result)
|
21
29
|
end
|
22
|
-
SExprInteger.create(raw_result)
|
23
30
|
end
|
24
31
|
|
25
32
|
['+', plus_code]
|
26
33
|
end
|
27
34
|
|
35
|
+
def create_minus()
|
36
|
+
minus_code = ->(runtime, arglist) do
|
37
|
+
first_one = arglist.head.evaluate(runtime)
|
38
|
+
operands = arglist.tail.to_eval_enum(runtime)
|
39
|
+
raw_result = first_one.value
|
40
|
+
operands.each { |elem| raw_result -= elem.value }
|
41
|
+
if raw_result.kind_of?(Float)
|
42
|
+
SExprReal.create(raw_result)
|
43
|
+
else
|
44
|
+
SExprInteger.create(raw_result)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
['-', minus_code]
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_multiply()
|
52
|
+
multiply_code = ->(runtime, arglist) do
|
53
|
+
first_one = arglist.head.evaluate(runtime)
|
54
|
+
operands = arglist.tail.to_eval_enum(runtime)
|
55
|
+
raw_result = first_one.value
|
56
|
+
operands.each { |elem| raw_result *= elem.value }
|
57
|
+
if raw_result.kind_of?(Float)
|
58
|
+
SExprReal.create(raw_result)
|
59
|
+
else
|
60
|
+
SExprInteger.create(raw_result)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
['*', multiply_code]
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_divide()
|
68
|
+
divide_code = ->(runtime, arglist) do
|
69
|
+
first_one = arglist.head.evaluate(runtime)
|
70
|
+
operands = arglist.tail.to_eval_enum(runtime)
|
71
|
+
raw_result = first_one.value
|
72
|
+
operands.each { |elem| raw_result /= elem.value }
|
73
|
+
if raw_result.kind_of?(Float)
|
74
|
+
SExprReal.create(raw_result)
|
75
|
+
else
|
76
|
+
SExprInteger.create(raw_result)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
['/', divide_code]
|
81
|
+
end
|
82
|
+
|
28
83
|
def def_func(aRuntime, aPair)
|
29
84
|
func = PrimitiveFunc.new(aPair.first, aPair.last)
|
30
85
|
define(aRuntime, func.identifier, func)
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -104,13 +104,17 @@ module Skeem
|
|
104
104
|
|
105
105
|
def_delegator :@members, :first, :empty?
|
106
106
|
|
107
|
-
def initialize()
|
107
|
+
def initialize(theMembers)
|
108
108
|
super(nil)
|
109
|
-
@members = []
|
109
|
+
@members = theMembers.nil? ? [] : theMembers
|
110
110
|
end
|
111
111
|
|
112
|
-
def
|
113
|
-
members.
|
112
|
+
def head()
|
113
|
+
return members.first
|
114
|
+
end
|
115
|
+
|
116
|
+
def tail()
|
117
|
+
SExprList.new(members.slice(1..-1))
|
114
118
|
end
|
115
119
|
|
116
120
|
# Factory method.
|
@@ -139,8 +143,6 @@ module Skeem
|
|
139
143
|
|
140
144
|
alias children members
|
141
145
|
alias subnodes members
|
142
|
-
alias head first
|
143
|
-
alias tail rest
|
144
146
|
end # class
|
145
147
|
|
146
148
|
class ProcedureCall < SExprElement
|
@@ -150,16 +152,18 @@ module Skeem
|
|
150
152
|
def initialize(aPosition, anOperator, theOperands)
|
151
153
|
super(aPosition)
|
152
154
|
@operator = anOperator
|
153
|
-
@operands = SExprList.new
|
154
|
-
@operands.instance_variable_set(:@members, theOperands)
|
155
|
+
@operands = SExprList.new(theOperands)
|
155
156
|
end
|
156
157
|
|
157
158
|
def evaluate(aRuntime)
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
159
|
+
proc_key = operator.evaluate(aRuntime)
|
160
|
+
unless aRuntime.include?(proc_key.value)
|
161
|
+
err = StandardError
|
162
|
+
key = proc_key.kind_of?(SExprIdentifier) ? proc_key.value : proc_key
|
163
|
+
err_msg = "Unknown function '#{key}'"
|
164
|
+
raise err, err_msg
|
165
|
+
end
|
166
|
+
procedure = aRuntime.environment.bindings[proc_key.value]
|
163
167
|
result = procedure.call(aRuntime, self)
|
164
168
|
end
|
165
169
|
|
data/lib/skeem/version.rb
CHANGED
@@ -15,7 +15,7 @@ module Skeem
|
|
15
15
|
it 'should have a runtime object' do
|
16
16
|
expect(subject.runtime).to be_kind_of(Runtime)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it 'should come with built-in functions' do
|
20
20
|
expect(subject.runtime.environment).not_to be_empty
|
21
21
|
end
|
@@ -88,12 +88,38 @@ module Skeem
|
|
88
88
|
expect(result.value).to eq(predicted)
|
89
89
|
end
|
90
90
|
end
|
91
|
+
end # context
|
91
92
|
|
92
|
-
|
93
|
-
|
93
|
+
context 'Built-in primitive functions' do
|
94
|
+
it 'should support the addition of integers' do
|
95
|
+
result = subject.run('(+ 2 2)')
|
94
96
|
expect(result).to be_kind_of(SExprInteger)
|
95
|
-
expect(result.value).to eq(
|
97
|
+
expect(result.value).to eq(4)
|
96
98
|
end
|
99
|
+
|
100
|
+
it 'should support the addition of real numbers' do
|
101
|
+
result = subject.run('(+ 2 2.34)')
|
102
|
+
expect(result).to be_kind_of(SExprReal)
|
103
|
+
expect(result.value).to eq(4.34)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should support the product of numbers' do
|
107
|
+
result = subject.run('(* 2 3 4)')
|
108
|
+
expect(result).to be_kind_of(SExprInteger)
|
109
|
+
expect(result.value).to eq(24)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should support the division of numbers' do
|
113
|
+
result = subject.run('(/ 24 3)')
|
114
|
+
expect(result).to be_kind_of(SExprInteger)
|
115
|
+
expect(result.value).to eq(8)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should support the arithmetic expressions' do
|
119
|
+
result = subject.run('(+ (* 2 100) (* 1 10))')
|
120
|
+
expect(result).to be_kind_of(SExprInteger)
|
121
|
+
expect(result.value).to eq(210)
|
122
|
+
end
|
97
123
|
end # context
|
98
124
|
end # describe
|
99
125
|
end # module
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skeem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|