skeem 0.2.07 → 0.2.08
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 +13 -0
- data/README.md +1 -0
- data/lib/skeem/datum_dsl.rb +0 -1
- data/lib/skeem/grammar.rb +8 -8
- data/lib/skeem/primitive/primitive_builder.rb +72 -24
- data/lib/skeem/s_expr_builder.rb +1 -1
- data/lib/skeem/skm_compound_datum.rb +0 -55
- data/lib/skeem/skm_element.rb +5 -0
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/primitive/primitive_builder_spec.rb +26 -3
- data/spec/skeem/skm_compound_datum_spec.rb +0 -36
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd3683235600881fa4fdbef83d8921aff335ee90388eef9f564b60e3d9217e49
|
4
|
+
data.tar.gz: 90c6402cc9f6367438ff8121741222edeab5712f747d3e498dc4a55c50f7047b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc0e68b644a532d23a8dfac125a48cbb2cf6c13e83e051e7757bf516a80a0d2fc721ea8d85f50d00461d0fa90aaf3e9fac4536f4c2818fbf061ad35110b64288
|
7
|
+
data.tar.gz: 7c8ea63a8b08532d8112ae85d0ea93d8c999f87a92ed43e5e6e8e97e0f168de7a69bdaa2d3f72fe0b42f756c158d4e3bcdbb0897312a6ac8be160f657c5a3fa3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## [0.2.08] - 2019-06-02
|
2
|
+
- New standard procedures implemented: `assq`, `assv`
|
3
|
+
|
4
|
+
### Added
|
5
|
+
- File `primitive_builder.rb`. New methods for implementing `assq`, `assv`
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- File `README.md` Added mentions to new procedures.
|
9
|
+
|
10
|
+
### Removed
|
11
|
+
- Superseded class `SkmList` removed.
|
12
|
+
|
13
|
+
|
1
14
|
## [0.2.07] - 2019-05-31
|
2
15
|
- New standard procedures implemented: `list-copy`, `procedure?`, `apply` and `map`
|
3
16
|
|
data/README.md
CHANGED
@@ -252,6 +252,7 @@ This section lists the implemented standard procedures
|
|
252
252
|
|
253
253
|
#### List procedures
|
254
254
|
* `list?`, `null?`, `pair?`, `append`, `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`, `cons`, `length`, `list`, `list-copy`, `list->vector`, `set-car!`, `set-cdr!`
|
255
|
+
, `assq`, `assv`
|
255
256
|
|
256
257
|
#### String procedures
|
257
258
|
* `string?`, `string=?`, `string-append`, `string-length`, `string->symbol`
|
data/lib/skeem/datum_dsl.rb
CHANGED
@@ -104,7 +104,6 @@ module Skeem
|
|
104
104
|
# Conversion from Ruby object value to Skeem datum
|
105
105
|
def to_datum(aLiteral)
|
106
106
|
return aLiteral if aLiteral.kind_of?(SkmSimpleDatum)
|
107
|
-
return list(aLiteral.members) if aLiteral.kind_of?(SkmList)
|
108
107
|
return vector(aLiteral.members) if aLiteral.kind_of?(SkmVector)
|
109
108
|
return aLiteral if aLiteral.kind_of?(Primitive::PrimitiveProcedure)
|
110
109
|
|
data/lib/skeem/grammar.rb
CHANGED
@@ -34,15 +34,15 @@ module Skeem
|
|
34
34
|
rule('definition' => 'LPAREN DEFINE IDENTIFIER expression RPAREN').as 'definition'
|
35
35
|
rule('definition' => 'LPAREN DEFINE LPAREN IDENTIFIER def_formals RPAREN body RPAREN').as 'alt_definition'
|
36
36
|
rule('definition' => 'LPAREN BEGIN definition_star RPAREN').as 'definitions_within_begin'
|
37
|
-
rule('expression' =>
|
38
|
-
rule 'expression' =>
|
39
|
-
rule 'expression' =>
|
40
|
-
rule 'expression' =>
|
41
|
-
rule 'expression' =>
|
42
|
-
rule 'expression' =>
|
43
|
-
rule 'expression' =>
|
37
|
+
rule('expression' => 'IDENTIFIER').as 'variable_reference'
|
38
|
+
rule 'expression' => 'literal'
|
39
|
+
rule 'expression' => 'procedure_call'
|
40
|
+
rule 'expression' => 'lambda_expression'
|
41
|
+
rule 'expression' => 'conditional'
|
42
|
+
rule 'expression' => 'assignment'
|
43
|
+
rule 'expression' => 'derived_expression'
|
44
44
|
rule 'literal' => 'quotation'
|
45
|
-
rule 'literal' => 'self-evaluating'
|
45
|
+
rule 'literal' => 'self-evaluating'
|
46
46
|
rule('quotation' => 'APOSTROPHE datum').as 'quotation_short'
|
47
47
|
rule('quotation' => 'LPAREN QUOTE datum RPAREN').as 'quotation'
|
48
48
|
rule 'self-evaluating' => 'BOOLEAN'
|
@@ -61,6 +61,7 @@ module Skeem
|
|
61
61
|
|
62
62
|
def add_comparison(aRuntime)
|
63
63
|
create_eqv?(aRuntime)
|
64
|
+
create_eq?(aRuntime)
|
64
65
|
create_equal?(aRuntime)
|
65
66
|
create_equal(aRuntime)
|
66
67
|
create_lt(aRuntime)
|
@@ -220,17 +221,36 @@ module Skeem
|
|
220
221
|
define_primitive_proc(aRuntime, 'floor-remainder', binary, primitive)
|
221
222
|
end
|
222
223
|
|
224
|
+
def core_eqv?(eval_arg1, eval_arg2)
|
225
|
+
raw_result = eval_arg1.eqv?(eval_arg2)
|
226
|
+
boolean(raw_result)
|
227
|
+
end
|
228
|
+
|
223
229
|
def create_eqv?(aRuntime)
|
224
230
|
primitive = ->(runtime, argument1, argument2) do
|
225
231
|
operand_1 = argument1.evaluate(runtime)
|
226
232
|
operand_2 = argument2.evaluate(runtime)
|
227
|
-
|
228
|
-
boolean(raw_result)
|
233
|
+
core_eqv?(operand_1, operand_2)
|
229
234
|
end
|
230
235
|
|
231
236
|
define_primitive_proc(aRuntime, 'eqv?', binary, primitive)
|
232
237
|
end
|
233
238
|
|
239
|
+
def core_eq?(eval_arg1, eval_arg2)
|
240
|
+
raw_result = eval_arg1.skm_eq?(eval_arg2)
|
241
|
+
boolean(raw_result)
|
242
|
+
end
|
243
|
+
|
244
|
+
def create_eq?(aRuntime)
|
245
|
+
primitive = ->(runtime, argument1, argument2) do
|
246
|
+
operand_1 = argument1.evaluate(runtime)
|
247
|
+
operand_2 = argument2.evaluate(runtime)
|
248
|
+
core_eq?(operand1, operand2)
|
249
|
+
end
|
250
|
+
|
251
|
+
define_primitive_proc(aRuntime, 'eq?', binary, primitive)
|
252
|
+
end
|
253
|
+
|
234
254
|
def create_equal?(aRuntime)
|
235
255
|
primitive = ->(runtime, argument1, argument2) do
|
236
256
|
operand_1 = argument1.evaluate(runtime)
|
@@ -355,7 +375,7 @@ module Skeem
|
|
355
375
|
argument = raw_arg.evaluate(aRuntime)
|
356
376
|
last_result = argument
|
357
377
|
raw_result &&= !(argument.boolean? && !argument.value)
|
358
|
-
break unless raw_result
|
378
|
+
break unless raw_result # stop here, a false was found...
|
359
379
|
end
|
360
380
|
raw_result = last_result if raw_result
|
361
381
|
# $stderr.puts raw_result.inspect
|
@@ -379,7 +399,7 @@ module Skeem
|
|
379
399
|
argument = raw_arg.evaluate(aRuntime)
|
380
400
|
last_result = argument
|
381
401
|
raw_result ||= (!argument.boolean? || argument.value)
|
382
|
-
break if raw_result
|
402
|
+
break if raw_result # stop here, a true was found...
|
383
403
|
end
|
384
404
|
raw_result = last_result if raw_result
|
385
405
|
to_datum(raw_result)
|
@@ -596,36 +616,64 @@ module Skeem
|
|
596
616
|
define_primitive_proc(aRuntime, 'set-cdr!', binary, primitive)
|
597
617
|
end
|
598
618
|
|
599
|
-
# create_assv(aRuntime)
|
600
619
|
def create_assq(aRuntime)
|
601
620
|
primitive = ->(runtime, obj_arg, alist_arg) do
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
621
|
+
assoc_list = alist_arg.evaluate(runtime)
|
622
|
+
check_assoc_list(assoc_list, 'assq')
|
623
|
+
obj = obj_arg.evaluate(runtime)
|
624
|
+
result = boolean(false)
|
625
|
+
unless assoc_list.empty?
|
626
|
+
pair = assoc_list
|
627
|
+
begin
|
628
|
+
are_equal = core_eq?(pair.car.car, obj)
|
629
|
+
if are_equal.value
|
630
|
+
result = pair.car
|
631
|
+
break
|
632
|
+
end
|
633
|
+
pair = pair.cdr
|
634
|
+
end while (pair && (pair.kind_of?(SkmPair)))
|
635
|
+
end
|
636
|
+
|
637
|
+
result
|
617
638
|
end
|
618
639
|
define_primitive_proc(aRuntime, 'assq', binary, primitive)
|
619
640
|
end
|
641
|
+
|
642
|
+
def create_assv(aRuntime)
|
643
|
+
primitive = ->(runtime, obj_arg, alist_arg) do
|
644
|
+
assoc_list = alist_arg.evaluate(runtime)
|
645
|
+
check_assoc_list(assoc_list, 'assq')
|
646
|
+
obj = obj_arg.evaluate(runtime)
|
647
|
+
result = boolean(false)
|
648
|
+
unless assoc_list.empty?
|
649
|
+
pair = assoc_list
|
650
|
+
begin
|
651
|
+
are_equal = core_eqv?(pair.car.car, obj)
|
652
|
+
if are_equal.value
|
653
|
+
result = pair.car
|
654
|
+
break
|
655
|
+
end
|
656
|
+
pair = pair.cdr
|
657
|
+
end while (pair && (pair.kind_of?(SkmPair)))
|
658
|
+
end
|
659
|
+
|
660
|
+
result
|
661
|
+
end
|
662
|
+
define_primitive_proc(aRuntime, 'assv', binary, primitive)
|
663
|
+
end
|
620
664
|
|
621
665
|
def check_assoc_list(alist, proc_name)
|
622
|
-
check_argtype(alist, SkmPair, 'association list',
|
623
|
-
end
|
666
|
+
check_argtype(alist, [SkmPair, SkmEmptyList], 'association list', proc_name)
|
624
667
|
|
625
|
-
|
668
|
+
unless alist.empty?
|
669
|
+
cell = SkmPair.new(integer(1), alist)
|
670
|
+
begin
|
671
|
+
cell = cell.cdr
|
672
|
+
check_argtype(cell, SkmPair, 'association list', proc_name)
|
673
|
+
end while cell.cdr.kind_of?(SkmPair)
|
674
|
+
end
|
626
675
|
end
|
627
676
|
|
628
|
-
|
629
677
|
def create_list_copy(aRuntime)
|
630
678
|
primitive = ->(runtime, arg) do
|
631
679
|
arg_evaluated = arg.evaluate(runtime)
|
data/lib/skeem/s_expr_builder.rb
CHANGED
@@ -86,7 +86,7 @@ module Skeem
|
|
86
86
|
# rule('expression' => 'IDENTIFIER').as 'variable_reference'
|
87
87
|
def reduce_variable_reference(_production, aRange, _tokens, theChildren)
|
88
88
|
SkmVariableReference.new(aRange, theChildren[0])
|
89
|
-
end
|
89
|
+
end
|
90
90
|
|
91
91
|
# rule('quotation' => 'APOSTROPHE datum').as 'quotation_short'
|
92
92
|
def reduce_quotation_short(_production, _range, _tokens, theChildren)
|
@@ -72,61 +72,6 @@ module Skeem
|
|
72
72
|
end
|
73
73
|
end # class
|
74
74
|
|
75
|
-
# @deprecated Use {#SkmPair} class instead.
|
76
|
-
class SkmList < SkmCompoundDatum
|
77
|
-
def tail()
|
78
|
-
SkmList.new(members.slice(1..-1))
|
79
|
-
end
|
80
|
-
|
81
|
-
def list?
|
82
|
-
true
|
83
|
-
end
|
84
|
-
|
85
|
-
def null?
|
86
|
-
empty?
|
87
|
-
end
|
88
|
-
|
89
|
-
def evaluate(aRuntime)
|
90
|
-
if empty?
|
91
|
-
self.class.new(nil)
|
92
|
-
else
|
93
|
-
first_evaluated = members.first.evaluate(aRuntime)
|
94
|
-
|
95
|
-
if first_evaluated.kind_of?(SkmIdentifier)
|
96
|
-
aRuntime.evaluate_form(self)
|
97
|
-
else
|
98
|
-
members_eval = members.map { |elem| elem.evaluate(aRuntime) }
|
99
|
-
self.class.new(members_eval)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
# Factory method.
|
106
|
-
# Construct an Enumerator that will return iteratively the result
|
107
|
-
# of 'evaluate' method of each members of self.
|
108
|
-
def to_eval_enum(aRuntime)
|
109
|
-
=begin
|
110
|
-
elements = self.members
|
111
|
-
|
112
|
-
new_enum = Enumerator.new do |result|
|
113
|
-
context = aRuntime
|
114
|
-
elements.each { |elem| result << elem.evaluate(context) }
|
115
|
-
end
|
116
|
-
|
117
|
-
new_enum
|
118
|
-
=end
|
119
|
-
members.map { |elem| elem.evaluate(aRuntime) }
|
120
|
-
end
|
121
|
-
|
122
|
-
def done!()
|
123
|
-
# Do nothing
|
124
|
-
end
|
125
|
-
|
126
|
-
alias head first
|
127
|
-
alias rest tail
|
128
|
-
end # class
|
129
|
-
|
130
75
|
class SkmVector < SkmCompoundDatum
|
131
76
|
def vector?
|
132
77
|
true
|
data/lib/skeem/skm_element.rb
CHANGED
@@ -61,6 +61,11 @@ module Skeem
|
|
61
61
|
msg = "Missing implementation of method #{self.class.name}##{__method__}"
|
62
62
|
raise NotImplementedError, msg
|
63
63
|
end
|
64
|
+
|
65
|
+
def skm_eq?(other)
|
66
|
+
# Default implementation, to override when necessary
|
67
|
+
self.eqv?(other)
|
68
|
+
end
|
64
69
|
|
65
70
|
# @return [TrueClass, FalseClass] true if quoted element is identical to itself
|
66
71
|
def verbatim?
|
data/lib/skeem/version.rb
CHANGED
@@ -634,6 +634,29 @@ SKEEM
|
|
634
634
|
expect(result.last.cdr).to eq(1)
|
635
635
|
end
|
636
636
|
|
637
|
+
it 'should implement the assq procedure' do
|
638
|
+
subject.run("(define e '((a 1) (b 2) (c 3)))")
|
639
|
+
result = subject.run("(assq 'a e)")
|
640
|
+
expect(result.to_a).to eq(['a', 1])
|
641
|
+
result = subject.run("(assq 'b e)")
|
642
|
+
expect(result.to_a).to eq(['b', 2])
|
643
|
+
result = subject.run("(assq 'c e)")
|
644
|
+
expect(result.to_a).to eq(['c', 3])
|
645
|
+
result = subject.run("(assq 'd e)")
|
646
|
+
expect(result).to eq(false)
|
647
|
+
result = subject.run("(assq 'a '())")
|
648
|
+
expect(result).to eq(false)
|
649
|
+
result = subject.run("(assq 'a '())")
|
650
|
+
expect(result).to eq(false)
|
651
|
+
result = subject.run("(assq '(a) '(((a)) ((b)) ((c))))")
|
652
|
+
expect(result).to eq(false)
|
653
|
+
end
|
654
|
+
|
655
|
+
it 'should implement the assv procedure' do
|
656
|
+
result = subject.run("(assv 5 '((2 3) (5 7) (11 13)))")
|
657
|
+
expect(result.to_a).to eq([5, 7])
|
658
|
+
end
|
659
|
+
|
637
660
|
it 'should implement the list-copy procedure' do
|
638
661
|
checks = [
|
639
662
|
["(list-copy '())", []],
|
@@ -737,7 +760,7 @@ SKEEM
|
|
737
760
|
["(procedure? car)", true],
|
738
761
|
["(procedure? 'car)", false],
|
739
762
|
["(procedure? (lambda (x) (* x x)))", true],
|
740
|
-
# ["(procedure? '(lambda (x) (* x x)))", false] # Parse
|
763
|
+
# ["(procedure? '(lambda (x) (* x x)))", false] # Parse fail: non-standard syntax
|
741
764
|
]
|
742
765
|
checks.each do |(skeem_expr, expectation)|
|
743
766
|
result = subject.run(skeem_expr)
|
@@ -754,7 +777,7 @@ SKEEM
|
|
754
777
|
expect(result).to eq(expectation)
|
755
778
|
end
|
756
779
|
end
|
757
|
-
|
780
|
+
|
758
781
|
it 'should implement the map procedure' do
|
759
782
|
checks = [
|
760
783
|
["(map car '((a b) (d e) (g h)))", ['a', 'd', 'g']],
|
@@ -764,7 +787,7 @@ SKEEM
|
|
764
787
|
result = subject.run(skeem_expr)
|
765
788
|
expect(result.to_a).to eq(expectation)
|
766
789
|
end
|
767
|
-
end
|
790
|
+
end
|
768
791
|
end # context
|
769
792
|
|
770
793
|
context 'IO procedures:' do
|
@@ -78,42 +78,6 @@ module Skeem
|
|
78
78
|
end
|
79
79
|
end # context
|
80
80
|
end # describe
|
81
|
-
|
82
|
-
describe SkmList do
|
83
|
-
let(:sample_members) { [1, 2, 3] }
|
84
|
-
subject { SkmList.new(sample_members) }
|
85
|
-
|
86
|
-
context 'Initialization:' do
|
87
|
-
it 'should be initialized with its members' do
|
88
|
-
expect{ SkmList.new(sample_members) }.not_to raise_error
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'should react positively to list? predicate' do
|
92
|
-
expect(subject).to be_list
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should react correctly to null? predicate' do
|
96
|
-
expect(subject).not_to be_null
|
97
|
-
expect(SkmList.new([])).to be_null
|
98
|
-
end
|
99
|
-
end # context
|
100
|
-
|
101
|
-
context 'Provided services:' do
|
102
|
-
it 'should retrieve its first member' do
|
103
|
-
expect(subject.first).to eq(1)
|
104
|
-
expect(subject.head).to eq(1)
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should retrieve its tail members' do
|
108
|
-
expect(subject.tail.inspect).to eq('<Skeem::SkmList: 2, 3>')
|
109
|
-
expect(subject.rest.inspect).to eq('<Skeem::SkmList: 2, 3>')
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'should return its text representation' do
|
113
|
-
expect(subject.inspect).to eq('<Skeem::SkmList: 1, 2, 3>')
|
114
|
-
end
|
115
|
-
end # context
|
116
|
-
end # describe
|
117
81
|
|
118
82
|
describe SkmVector do
|
119
83
|
let(:sample_members) { [1, 2, 3] }
|
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.2.
|
4
|
+
version: 0.2.08
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|