skeem 0.2.15 → 0.2.16
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/.rubocop.yml +17 -11
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/README.md +3 -2
- data/Rakefile +2 -0
- data/appveyor.yml +3 -4
- data/bin/skeem +15 -15
- data/lib/skeem.rb +2 -0
- data/lib/skeem/datum_dsl.rb +12 -3
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +86 -24
- data/lib/skeem/interpreter.rb +5 -3
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +128 -115
- data/lib/skeem/primitive/primitive_procedure.rb +17 -20
- data/lib/skeem/runtime.rb +9 -5
- data/lib/skeem/s_expr_builder.rb +46 -104
- data/lib/skeem/s_expr_nodes.rb +116 -90
- data/lib/skeem/skeem_exception.rb +0 -0
- data/lib/skeem/skm_binding.rb +6 -7
- data/lib/skeem/skm_compound_datum.rb +8 -4
- data/lib/skeem/skm_element.rb +14 -12
- data/lib/skeem/skm_empty_list.rb +6 -4
- data/lib/skeem/skm_exception.rb +9 -0
- data/lib/skeem/skm_expression.rb +3 -1
- data/lib/skeem/skm_frame.rb +3 -2
- data/lib/skeem/skm_pair.rb +23 -18
- data/lib/skeem/skm_procedure_exec.rb +8 -6
- data/lib/skeem/skm_simple_datum.rb +13 -12
- data/lib/skeem/skm_unary_expression.rb +15 -17
- data/lib/skeem/tokenizer.rb +32 -25
- data/lib/skeem/version.rb +3 -1
- data/skeem.gemspec +6 -4
- data/spec/skeem/add4.skm +4 -0
- data/spec/skeem/datum_dsl_spec.rb +13 -12
- data/spec/skeem/element_visitor_spec.rb +12 -10
- data/spec/skeem/interpreter_spec.rb +74 -46
- data/spec/skeem/lambda_spec.rb +9 -7
- data/spec/skeem/parser_spec.rb +21 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +57 -48
- data/spec/skeem/primitive/primitive_procedure_spec.rb +15 -13
- data/spec/skeem/runtime_spec.rb +18 -16
- data/spec/skeem/s_expr_nodes_spec.rb +8 -6
- data/spec/skeem/skm_compound_datum_spec.rb +11 -9
- data/spec/skeem/skm_element_spec.rb +7 -5
- data/spec/skeem/skm_empty_list_spec.rb +7 -5
- data/spec/skeem/skm_frame_spec.rb +5 -4
- data/spec/skeem/skm_pair_spec.rb +4 -3
- data/spec/skeem/skm_procedure_exec_spec.rb +2 -0
- data/spec/skeem/skm_simple_datum_spec.rb +24 -22
- data/spec/skeem/skm_unary_expression_spec.rb +11 -9
- data/spec/skeem/tokenizer_spec.rb +53 -44
- data/spec/skeem_spec.rb +2 -0
- data/spec/spec_helper.rb +4 -2
- metadata +7 -4
File without changes
|
data/lib/skeem/skm_binding.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'skm_element'
|
2
4
|
|
3
5
|
module Skeem
|
4
|
-
|
5
6
|
# An identifier that is not a syntactic keyword can be used as a variable.
|
6
7
|
# A variable may give a name to value that is bound (i.e. associated)
|
7
8
|
# to that variable.
|
@@ -56,26 +57,24 @@ module Skeem
|
|
56
57
|
|
57
58
|
result
|
58
59
|
end
|
59
|
-
|
60
60
|
end # class
|
61
61
|
|
62
62
|
|
63
63
|
class SkmUpdateBinding < SkmBinding
|
64
|
-
|
65
64
|
protected
|
66
65
|
|
67
66
|
def binding_action(aRuntime, anIdentifier, anExpression)
|
68
67
|
aRuntime.update_binding(anIdentifier, anExpression)
|
69
68
|
end
|
70
69
|
end # class
|
71
|
-
|
70
|
+
|
72
71
|
class SkmDelayedUpdateBinding < SkmBinding
|
73
72
|
attr_reader :new_val
|
74
|
-
|
73
|
+
|
75
74
|
def initialize(anIdentifier, aValue)
|
76
75
|
super(anIdentifier, aValue)
|
77
76
|
end
|
78
|
-
|
77
|
+
|
79
78
|
def do_it!(aRuntime)
|
80
79
|
aRuntime.update_binding(variable, new_val)
|
81
80
|
end
|
@@ -85,5 +84,5 @@ module Skeem
|
|
85
84
|
def binding_action(_runtime, _identifier, anExpression)
|
86
85
|
@new_val = anExpression
|
87
86
|
end
|
88
|
-
end # class
|
87
|
+
end # class
|
89
88
|
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
4
|
require_relative 'skm_element'
|
3
5
|
|
@@ -18,13 +20,15 @@ module Skeem
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def ==(other)
|
21
|
-
return true if
|
23
|
+
return true if equal?(other)
|
24
|
+
|
22
25
|
result = case other
|
23
26
|
when SkmCompoundDatum
|
24
|
-
self.class == other.class &&
|
27
|
+
self.class == other.class && members == other.members
|
25
28
|
when Array
|
26
29
|
members == other
|
27
30
|
end
|
31
|
+
result
|
28
32
|
end
|
29
33
|
|
30
34
|
alias eqv? equal?
|
@@ -65,7 +69,7 @@ module Skeem
|
|
65
69
|
protected
|
66
70
|
|
67
71
|
def inspect_specific
|
68
|
-
result = ''
|
72
|
+
result = +''
|
69
73
|
members.each { |elem| result << elem.inspect + ', ' }
|
70
74
|
result.sub!(/, $/, '')
|
71
75
|
result
|
@@ -77,4 +81,4 @@ module Skeem
|
|
77
81
|
true
|
78
82
|
end
|
79
83
|
end # class
|
80
|
-
end # module
|
84
|
+
end # module
|
data/lib/skeem/skm_element.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Skeem
|
2
4
|
# Abstract class. Generalization of any S-expr element.
|
3
5
|
SkmElement = Struct.new(:position) do
|
4
6
|
def initialize(aPosition)
|
5
7
|
self.position = aPosition
|
6
8
|
end
|
7
|
-
|
9
|
+
|
8
10
|
def callable?
|
9
11
|
false
|
10
12
|
end
|
@@ -12,15 +14,15 @@ module Skeem
|
|
12
14
|
def number?
|
13
15
|
false
|
14
16
|
end
|
15
|
-
|
17
|
+
|
16
18
|
def complex?
|
17
19
|
false
|
18
|
-
end
|
20
|
+
end
|
19
21
|
|
20
22
|
def real?
|
21
23
|
false
|
22
24
|
end
|
23
|
-
|
25
|
+
|
24
26
|
def rational?
|
25
27
|
false
|
26
28
|
end
|
@@ -32,7 +34,7 @@ module Skeem
|
|
32
34
|
def boolean?
|
33
35
|
false
|
34
36
|
end
|
35
|
-
|
37
|
+
|
36
38
|
def char?
|
37
39
|
false
|
38
40
|
end
|
@@ -56,7 +58,7 @@ module Skeem
|
|
56
58
|
def pair?
|
57
59
|
false
|
58
60
|
end
|
59
|
-
|
61
|
+
|
60
62
|
def procedure?
|
61
63
|
false
|
62
64
|
end
|
@@ -73,11 +75,11 @@ module Skeem
|
|
73
75
|
msg = "Missing implementation of method #{self.class.name}##{__method__}"
|
74
76
|
raise NotImplementedError, msg
|
75
77
|
end
|
76
|
-
|
78
|
+
|
77
79
|
def skm_eq?(other)
|
78
80
|
# Default implementation, to override when necessary
|
79
|
-
|
80
|
-
end
|
81
|
+
eqv?(other)
|
82
|
+
end
|
81
83
|
|
82
84
|
# @return [TrueClass, FalseClass] true if quoted element is identical to itself
|
83
85
|
def verbatim?
|
@@ -117,8 +119,8 @@ module Skeem
|
|
117
119
|
# Do nothing
|
118
120
|
end
|
119
121
|
|
120
|
-
|
121
|
-
result = inspect_prefix
|
122
|
+
def inspect
|
123
|
+
result = inspect_prefix.dup
|
122
124
|
result << inspect_specific
|
123
125
|
result << inspect_suffix
|
124
126
|
|
@@ -139,4 +141,4 @@ module Skeem
|
|
139
141
|
raise NotImplementedError, "Missing #{self.class.to_s + '#' + 'inspect_specific'}"
|
140
142
|
end
|
141
143
|
end # struct
|
142
|
-
end # module
|
144
|
+
end # module
|
data/lib/skeem/skm_empty_list.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'singleton'
|
2
4
|
require_relative 'skm_element'
|
3
5
|
|
@@ -42,7 +44,7 @@ module Skeem
|
|
42
44
|
def klone
|
43
45
|
self
|
44
46
|
end
|
45
|
-
|
47
|
+
|
46
48
|
def append_list(aList)
|
47
49
|
aList
|
48
50
|
end
|
@@ -64,14 +66,14 @@ module Skeem
|
|
64
66
|
protected
|
65
67
|
|
66
68
|
def inspect_specific
|
67
|
-
'()'
|
69
|
+
+'()'
|
68
70
|
end
|
69
71
|
|
70
72
|
private
|
71
73
|
|
72
|
-
def initialize
|
74
|
+
def initialize
|
73
75
|
super(0)
|
74
|
-
|
76
|
+
freeze
|
75
77
|
end
|
76
78
|
end # class
|
77
79
|
end # module
|
data/lib/skeem/skm_expression.rb
CHANGED
data/lib/skeem/skm_frame.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'skm_simple_datum'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -139,6 +141,5 @@ module Skeem
|
|
139
141
|
# Notify the value that it is bound to a variable from this frame.
|
140
142
|
anExpression.bound!(self)
|
141
143
|
end
|
142
|
-
|
143
144
|
end # class
|
144
|
-
end # module
|
145
|
+
end # module
|
data/lib/skeem/skm_pair.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'skm_empty_list'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -41,11 +43,12 @@ module Skeem
|
|
41
43
|
def self.create_from_a(anArray)
|
42
44
|
current = nil
|
43
45
|
return SkmEmptyList.instance if anArray.empty?
|
46
|
+
|
44
47
|
anArray.reverse_each do |elem|
|
45
48
|
if current.nil?
|
46
|
-
current =
|
49
|
+
current = new(elem, SkmEmptyList.instance)
|
47
50
|
else
|
48
|
-
current =
|
51
|
+
current = new(elem, current)
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
@@ -54,6 +57,7 @@ module Skeem
|
|
54
57
|
|
55
58
|
def empty?
|
56
59
|
return false if car
|
60
|
+
|
57
61
|
if [SkmPair, SkmEmptyList].include? cdr.class
|
58
62
|
cdr.empty?
|
59
63
|
else
|
@@ -92,20 +96,20 @@ module Skeem
|
|
92
96
|
end
|
93
97
|
|
94
98
|
def last_pair
|
95
|
-
if cdr.nil? || (cdr == SkmEmptyList.instance) ||
|
99
|
+
if cdr.nil? || (cdr == SkmEmptyList.instance) || !cdr.kind_of?(SkmPair)
|
96
100
|
self
|
97
101
|
else
|
98
102
|
cdr.last_pair
|
99
103
|
end
|
100
104
|
end
|
101
|
-
|
105
|
+
|
102
106
|
def proper?
|
103
|
-
last_node =
|
107
|
+
last_node = last_pair
|
104
108
|
last_node.cdr.nil? || (last_node.cdr == SkmEmptyList.instance)
|
105
109
|
end
|
106
110
|
|
107
111
|
def last
|
108
|
-
|
112
|
+
to_a.last
|
109
113
|
end
|
110
114
|
|
111
115
|
def eqv?(_other)
|
@@ -138,7 +142,7 @@ module Skeem
|
|
138
142
|
end
|
139
143
|
|
140
144
|
def append(anElement)
|
141
|
-
last_one =
|
145
|
+
last_one = last_pair
|
142
146
|
if last_one.cdr.nil? || last_one.cdr.kind_of?(SkmEmptyList)
|
143
147
|
last_one.cdr = SkmPair.new(anElement, SkmEmptyList.instance)
|
144
148
|
else
|
@@ -147,7 +151,7 @@ module Skeem
|
|
147
151
|
end
|
148
152
|
|
149
153
|
def append_list(aList)
|
150
|
-
last_one =
|
154
|
+
last_one = last_pair
|
151
155
|
if last_one.cdr.nil? || last_one.cdr.kind_of?(SkmEmptyList)
|
152
156
|
last_one.cdr = aList
|
153
157
|
else
|
@@ -157,22 +161,23 @@ module Skeem
|
|
157
161
|
|
158
162
|
def evaluate(aRuntime)
|
159
163
|
return SkmEmptyList.instance if empty?
|
164
|
+
|
160
165
|
if car.kind_of?(SkmIdentifier) && car.is_var_name
|
161
166
|
result = aRuntime.evaluate_form(self)
|
162
167
|
else
|
163
168
|
begin
|
164
169
|
result = clone_evaluate(aRuntime)
|
165
|
-
rescue NoMethodError =>
|
166
|
-
$stderr.puts 'SkmPair#evaluate: ' +
|
167
|
-
$stderr.puts 'SkmPair as Array: ' +
|
168
|
-
raise
|
170
|
+
rescue NoMethodError => e
|
171
|
+
$stderr.puts 'SkmPair#evaluate: ' + inspect
|
172
|
+
$stderr.puts 'SkmPair as Array: ' + to_a.inspect
|
173
|
+
raise e
|
169
174
|
end
|
170
175
|
end
|
171
176
|
result
|
172
177
|
end
|
173
178
|
|
174
179
|
def quasiquote(aRuntime)
|
175
|
-
members_eval =
|
180
|
+
members_eval = to_a.map { |elem| elem.quasiquote(aRuntime) }
|
176
181
|
self.class.create_from_a(members_eval)
|
177
182
|
end
|
178
183
|
|
@@ -184,16 +189,17 @@ module Skeem
|
|
184
189
|
|
185
190
|
def quoted!
|
186
191
|
car.quoted!
|
187
|
-
cdr
|
192
|
+
cdr&.quoted!
|
188
193
|
end
|
189
194
|
|
190
195
|
def unquoted!
|
191
196
|
car.unquoted!
|
192
|
-
cdr
|
197
|
+
cdr&.unquoted!
|
193
198
|
end
|
194
199
|
|
195
|
-
def verbatim?
|
200
|
+
def verbatim?
|
196
201
|
return false unless car.verbatim?
|
202
|
+
|
197
203
|
if cdr.nil?
|
198
204
|
true
|
199
205
|
else
|
@@ -211,6 +217,5 @@ module Skeem
|
|
211
217
|
|
212
218
|
result
|
213
219
|
end
|
214
|
-
|
215
220
|
end # class
|
216
|
-
end # module
|
221
|
+
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'runtime'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -27,18 +29,18 @@ module Skeem
|
|
27
29
|
result = definition.evaluate_sequence(runtime)
|
28
30
|
runtime.pop
|
29
31
|
# $stderr.puts "Lambda result: #{result.object_id.to_s(16)}" if result.kind_of?(SkmLambda)
|
30
|
-
|
32
|
+
|
31
33
|
result
|
32
34
|
end
|
33
|
-
|
35
|
+
|
34
36
|
private
|
35
|
-
|
37
|
+
|
36
38
|
def evaluate_defs(aRuntime)
|
37
39
|
definition.definitions.each do |bndng|
|
38
|
-
val = bndng.value.evaluate(aRuntime)
|
40
|
+
val = bndng.value.evaluate(aRuntime)
|
39
41
|
var = bndng.variable.evaluate(aRuntime)
|
40
42
|
frame.add_binding(var, val)
|
41
|
-
end
|
43
|
+
end
|
42
44
|
end
|
43
45
|
end # class
|
44
|
-
end # module
|
46
|
+
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'skm_element'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -14,7 +16,7 @@ module Skeem
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def self.create(aValue)
|
17
|
-
lightweight =
|
19
|
+
lightweight = allocate
|
18
20
|
lightweight.init_value(aValue)
|
19
21
|
return lightweight
|
20
22
|
end
|
@@ -33,12 +35,12 @@ module Skeem
|
|
33
35
|
# @param other [SkmSimpleDatum, Object] object to compare with.
|
34
36
|
# @return [TrueClass, FalseClass]
|
35
37
|
def ==(other)
|
36
|
-
return true if
|
38
|
+
return true if equal?(other)
|
37
39
|
|
38
40
|
result = if other.kind_of?(SkmSimpleDatum)
|
39
|
-
|
41
|
+
value == other.value
|
40
42
|
else
|
41
|
-
|
43
|
+
value == other
|
42
44
|
end
|
43
45
|
|
44
46
|
result
|
@@ -51,7 +53,7 @@ module Skeem
|
|
51
53
|
true
|
52
54
|
end
|
53
55
|
|
54
|
-
def done!
|
56
|
+
def done!
|
55
57
|
# Do nothing
|
56
58
|
end
|
57
59
|
|
@@ -103,16 +105,16 @@ module Skeem
|
|
103
105
|
end
|
104
106
|
|
105
107
|
def eqv?(other)
|
106
|
-
return true if
|
108
|
+
return true if equal?(other)
|
107
109
|
|
108
110
|
result = if other.kind_of?(SkmNumber)
|
109
|
-
if
|
111
|
+
if exact? != other.exact?
|
110
112
|
false
|
111
113
|
else
|
112
|
-
|
114
|
+
value == other.value
|
113
115
|
end
|
114
116
|
else
|
115
|
-
|
117
|
+
value == other
|
116
118
|
end
|
117
119
|
|
118
120
|
result
|
@@ -159,7 +161,6 @@ module Skeem
|
|
159
161
|
char_value = int_value < 0xff ? int_value.chr : [int_value].pack('U')
|
160
162
|
create(char_value)
|
161
163
|
end
|
162
|
-
|
163
164
|
end # class
|
164
165
|
|
165
166
|
class SkmString < SkmSimpleDatum
|
@@ -199,7 +200,7 @@ module Skeem
|
|
199
200
|
end
|
200
201
|
|
201
202
|
def verbatim?
|
202
|
-
|
203
|
+
!is_var_name
|
203
204
|
end
|
204
205
|
|
205
206
|
def quoted!
|
@@ -213,4 +214,4 @@ module Skeem
|
|
213
214
|
|
214
215
|
class SkmReserved < SkmIdentifier
|
215
216
|
end # class
|
216
|
-
end # module
|
217
|
+
end # module
|