skeem 0.0.12 → 0.0.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +13 -3
- data/lib/skeem/grammar.rb +10 -5
- data/lib/skeem/s_expr_builder.rb +5 -0
- data/lib/skeem/s_expr_nodes.rb +31 -0
- data/lib/skeem/tokenizer.rb +1 -0
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/interpreter_spec.rb +31 -1
- 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: ba107706c9483fb97e9a628b621ca7932c00f16d
|
4
|
+
data.tar.gz: 14ddf9ec1cebab58ae123ffbef3786f306824cb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfb3e078734b6e7ed68161f095c5c5c3287afd8c4fd1583b7a0e7f1d79c112aead08dd4e95d804ee68d7bfc7c1da73841252ef8eb8acdf88700d929682a2dc35
|
7
|
+
data.tar.gz: 5fd3ed354914cb9af65fd0e7836d3a474c45f980fcbf4a0535162d08d8944f14e72f8168e723ea024f46b8861292d47ae0e53ba419250f38e4a2a5fd1df2aaf3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## [0.0.13] - 2018-09-18
|
2
|
+
Added primitive `if` (conditional form)
|
3
|
+
|
4
|
+
### Added
|
5
|
+
- Class `SkmCondition` for representing a specific conditional.
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- File `grammar.rb` Added syntax rules for conditional expression.
|
9
|
+
- Class `SkmBuilder`. Added method to implement the semantic action for `if`.
|
10
|
+
- File `interpreter_spec.rb` added tests for `if`.
|
11
|
+
- File `README.md` Changed demo snippet with example of conditional expression.
|
12
|
+
|
1
13
|
## [0.0.12] - 2018-09-17
|
2
14
|
Added primitive `define` and variable reference
|
3
15
|
|
data/README.md
CHANGED
@@ -31,15 +31,25 @@ At this stage, the gem consists of a bare-bones interpreter.
|
|
31
31
|
require 'skeem'
|
32
32
|
|
33
33
|
schemer = Skeem::Interpreter.new
|
34
|
+
|
34
35
|
scheme_code =<<-SKEEM
|
36
|
+
; This heredoc consists of Scheme code...
|
35
37
|
; Let's define a Scheme variable
|
36
38
|
(define foobar (* 2 3 7))
|
37
39
|
|
38
|
-
; Now
|
39
|
-
foobar
|
40
|
+
; Now test its value against a lower value
|
41
|
+
(if (> foobar 40) #true #false)
|
40
42
|
SKEEM
|
43
|
+
|
44
|
+
# Ask Ruby to execute Scheme code
|
45
|
+
result = schemer.run(scheme_code)
|
46
|
+
puts result.value # => true
|
47
|
+
|
48
|
+
# The interpreter object keeps the bindings of variable
|
49
|
+
# Let's test that...
|
50
|
+
scheme_code = '(* foobar foobar)'
|
41
51
|
result = schemer.run(scheme_code)
|
42
|
-
puts result.value # =>
|
52
|
+
puts result.value # => 1764
|
43
53
|
```
|
44
54
|
|
45
55
|
Roadmap:
|
data/lib/skeem/grammar.rb
CHANGED
@@ -8,8 +8,8 @@ module Skeem
|
|
8
8
|
# https://bitbucket.org/cowan/r7rs/src/draft-10/rnrs/r7rs.pdf
|
9
9
|
# Names of grammar elements are based on the R7RS documentation
|
10
10
|
builder = Rley::Syntax::GrammarBuilder.new do
|
11
|
-
#
|
12
|
-
# add_terminals('APOSTROPHE', 'BACKQUOTE')
|
11
|
+
# Delimiters, separators...
|
12
|
+
# add_terminals('APOSTROPHE', 'BACKQUOTE')
|
13
13
|
add_terminals('LPAREN', 'RPAREN')
|
14
14
|
# add_terminals('PERIOD')
|
15
15
|
|
@@ -18,9 +18,8 @@ module Skeem
|
|
18
18
|
add_terminals('STRING_LIT', 'IDENTIFIER')
|
19
19
|
|
20
20
|
# Keywords...
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
add_terminals('DEFINE', 'IF')
|
22
|
+
|
24
23
|
rule('program' => 'cmd_or_def_plus').as 'main'
|
25
24
|
rule('cmd_or_def_plus' => 'cmd_or_def_plus cmd_or_def').as 'multiple_cmd_def'
|
26
25
|
rule('cmd_or_def_plus' => 'cmd_or_def').as 'last_cmd_def'
|
@@ -31,6 +30,7 @@ module Skeem
|
|
31
30
|
rule('expression' => 'IDENTIFIER').as 'variable_reference'
|
32
31
|
rule 'expression' => 'literal'
|
33
32
|
rule 'expression' => 'procedure_call'
|
33
|
+
rule 'expression' => 'conditional'
|
34
34
|
rule 'literal' => 'self-evaluating'
|
35
35
|
rule 'self-evaluating' => 'BOOLEAN'
|
36
36
|
rule 'self-evaluating' => 'number'
|
@@ -41,6 +41,11 @@ module Skeem
|
|
41
41
|
rule('operand_plus' => 'operand').as 'last_operand'
|
42
42
|
rule 'operator' => 'expression'
|
43
43
|
rule 'operand' => 'expression'
|
44
|
+
rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
|
45
|
+
rule 'test' => 'expression'
|
46
|
+
rule 'consequent' => 'expression'
|
47
|
+
rule 'alternate' => 'expression'
|
48
|
+
rule 'alternate' => []
|
44
49
|
rule 'number' => 'INTEGER'
|
45
50
|
rule 'number' => 'REAL'
|
46
51
|
end
|
data/lib/skeem/s_expr_builder.rb
CHANGED
@@ -81,6 +81,11 @@ module Skeem
|
|
81
81
|
def reduce_last_operand(_production, _range, _tokens, theChildren)
|
82
82
|
[theChildren.last]
|
83
83
|
end
|
84
|
+
|
85
|
+
# rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
|
86
|
+
def reduce_conditional(_production, aRange, _tokens, theChildren)
|
87
|
+
SkmCondition.new(aRange, theChildren[2], theChildren[3], theChildren[4])
|
88
|
+
end
|
84
89
|
end # class
|
85
90
|
end # module
|
86
91
|
# End of file
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -4,6 +4,13 @@
|
|
4
4
|
require 'forwardable'
|
5
5
|
|
6
6
|
module Skeem
|
7
|
+
class SkmUndefined
|
8
|
+
def value
|
9
|
+
:UNDEFINED
|
10
|
+
end
|
11
|
+
end # class
|
12
|
+
|
13
|
+
|
7
14
|
# Abstract class. Generalization of any S-expr element.
|
8
15
|
SkmElement = Struct.new(:position) do
|
9
16
|
def initialize(aPosition)
|
@@ -272,5 +279,29 @@ module Skeem
|
|
272
279
|
|
273
280
|
alias children operands
|
274
281
|
end # class
|
282
|
+
|
283
|
+
class SkmCondition < SkmElement
|
284
|
+
attr_reader :test
|
285
|
+
attr_reader :consequent
|
286
|
+
attr_reader :alternate
|
287
|
+
|
288
|
+
def initialize(aPosition, aTest, aConsequent, anAlternate)
|
289
|
+
super(aPosition)
|
290
|
+
@test = aTest
|
291
|
+
@consequent = aConsequent
|
292
|
+
@alternate = anAlternate
|
293
|
+
end
|
294
|
+
|
295
|
+
def evaluate(aRuntime)
|
296
|
+
test_result = test.evaluate(aRuntime)
|
297
|
+
condition_result = nil
|
298
|
+
if test_result.boolean? && test_result.value == false
|
299
|
+
# Only #f is considered as false, everything else is true
|
300
|
+
condition_result = alternate ? alternate.evaluate(aRuntime) : SkmUndefined.new
|
301
|
+
else
|
302
|
+
condition_result = consequent.evaluate(aRuntime)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end # class
|
275
306
|
end # module
|
276
307
|
# End of file
|
data/lib/skeem/tokenizer.rb
CHANGED
data/lib/skeem/version.rb
CHANGED
@@ -93,7 +93,37 @@ SKEEM
|
|
93
93
|
result = subject.run(source)
|
94
94
|
expect(result).to be_kind_of(SkmInteger)
|
95
95
|
expect(result.value).to eq(28)
|
96
|
-
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should implement the simple conditional form' do
|
99
|
+
checks = [
|
100
|
+
['(if (> 3 2) "yes")', 'yes'],
|
101
|
+
['(if (> 2 3) "yes")', :UNDEFINED]
|
102
|
+
]
|
103
|
+
checks.each do |(skeem_expr, expectation)|
|
104
|
+
result = subject.run(skeem_expr)
|
105
|
+
expect(result.value).to eq(expectation)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should implement the complete conditional form' do
|
110
|
+
checks = [
|
111
|
+
['(if (> 3 2) "yes" "no")', 'yes'],
|
112
|
+
['(if (> 2 3) "yes" "no")', 'no']
|
113
|
+
]
|
114
|
+
checks.each do |(skeem_expr, expectation)|
|
115
|
+
result = subject.run(skeem_expr)
|
116
|
+
expect(result.value).to eq(expectation)
|
117
|
+
end
|
118
|
+
source = <<-SKEEM
|
119
|
+
; Example from R7RS section 4.1.5
|
120
|
+
(if (> 3 2)
|
121
|
+
(- 3 2)
|
122
|
+
(+ 3 2))
|
123
|
+
SKEEM
|
124
|
+
result = subject.run(source)
|
125
|
+
expect(result.value).to eq(1)
|
126
|
+
end
|
97
127
|
end # context
|
98
128
|
|
99
129
|
context 'Built-in primitive procedures' do
|
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.13
|
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-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|