skeem 0.2.14 → 0.2.18
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 +451 -195
- data/.travis.yml +27 -0
- data/CHANGELOG.md +35 -1
- data/Gemfile +2 -0
- data/README.md +125 -56
- data/Rakefile +2 -0
- data/appveyor.yml +3 -4
- data/bin/cubic.skm +4 -0
- data/bin/hello-world.skm +1 -0
- data/bin/skeem +72 -0
- data/lib/skeem/datum_dsl.rb +40 -30
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +88 -26
- data/lib/skeem/interpreter.rb +9 -7
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +148 -122
- data/lib/skeem/primitive/primitive_procedure.rb +23 -25
- data/lib/skeem/runtime.rb +17 -15
- data/lib/skeem/s_expr_builder.rb +49 -117
- data/lib/skeem/s_expr_nodes.rb +147 -132
- data/lib/skeem/skeem_exception.rb +1 -0
- data/lib/skeem/skm_binding.rb +9 -11
- data/lib/skeem/skm_compound_datum.rb +9 -6
- data/lib/skeem/skm_element.rb +15 -13
- 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 +26 -18
- data/lib/skeem/skm_procedure_exec.rb +11 -6
- data/lib/skeem/skm_simple_datum.rb +23 -20
- data/lib/skeem/skm_unary_expression.rb +34 -37
- data/lib/skeem/standard/base.skm +4 -0
- data/lib/skeem/tokenizer.rb +38 -28
- data/lib/skeem/version.rb +3 -1
- data/lib/skeem.rb +2 -0
- data/skeem.gemspec +9 -6
- data/spec/skeem/add4.skm +4 -0
- data/spec/skeem/datum_dsl_spec.rb +13 -12
- data/spec/skeem/element_visitor_spec.rb +14 -10
- data/spec/skeem/interpreter_spec.rb +84 -44
- data/spec/skeem/lambda_spec.rb +13 -11
- data/spec/skeem/parser_spec.rb +23 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +65 -48
- data/spec/skeem/primitive/primitive_procedure_spec.rb +14 -12
- data/spec/skeem/runtime_spec.rb +20 -18
- data/spec/skeem/s_expr_nodes_spec.rb +8 -6
- data/spec/skeem/skm_compound_datum_spec.rb +12 -10
- 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 +9 -8
- 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 +54 -43
- data/spec/skeem_spec.rb +2 -0
- data/spec/spec_helper.rb +15 -10
- metadata +18 -10
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative '../../spec_helper' # Use the RSpec framework
|
2
4
|
|
3
5
|
# Load the class under test
|
@@ -41,8 +43,8 @@ SKEEM
|
|
41
43
|
['(+)', 0], # '+' as nullary operator. Example from section 6.2.6
|
42
44
|
['(+ -3)', -3], # '+' as unary operator
|
43
45
|
['(+ 3 4)', 7], # '+' as binary operator. Example from section 4.1.3
|
44
|
-
['(+ 1/2 2/3)', Rational(7,6)],
|
45
|
-
['(+ 1/2 3)', Rational(7,2)],
|
46
|
+
['(+ 1/2 2/3)', Rational(7, 6)],
|
47
|
+
['(+ 1/2 3)', Rational(7, 2)],
|
46
48
|
['(+ 2 2.34)', 4.34]
|
47
49
|
]
|
48
50
|
compare_to_predicted(checks)
|
@@ -219,7 +221,7 @@ SKEEM
|
|
219
221
|
["(equal? (make-vector 5 'a) (make-vector 5 'a))", true],
|
220
222
|
['(equal? car car)', true],
|
221
223
|
['(equal? car cdr)', false],
|
222
|
-
['(equal? (lambda (x) x) (lambda (y) y))', false]
|
224
|
+
['(equal? (lambda (x) x) (lambda (y) y))', false]
|
223
225
|
]
|
224
226
|
compare_to_predicted(checks) do |result, expectation|
|
225
227
|
if result.length > 1
|
@@ -355,7 +357,7 @@ SKEEM
|
|
355
357
|
['(integer? "3")', false],
|
356
358
|
['(integer? #t)', false]
|
357
359
|
]
|
358
|
-
|
360
|
+
compare_to_predicted(checks)
|
359
361
|
end
|
360
362
|
|
361
363
|
it 'should implement the number->string procedure' do
|
@@ -396,7 +398,7 @@ SKEEM
|
|
396
398
|
['(or)', false],
|
397
399
|
['(or #f)', false],
|
398
400
|
['(or #f #t)', true],
|
399
|
-
['(or #f #f #f)', false]
|
401
|
+
['(or #f #f #f)', false]
|
400
402
|
|
401
403
|
]
|
402
404
|
compare_to_predicted(checks)
|
@@ -485,11 +487,11 @@ SKEEM
|
|
485
487
|
compare_to_predicted(checks)
|
486
488
|
end
|
487
489
|
|
488
|
-
|
490
|
+
it 'should implement the string-length procedure' do
|
489
491
|
checks = [
|
490
492
|
['(string-length "abc")', 3],
|
491
493
|
['(string-length "")', 0],
|
492
|
-
['(string-length "hi there")', 8]
|
494
|
+
['(string-length "hi there")', 8]
|
493
495
|
]
|
494
496
|
compare_to_predicted(checks)
|
495
497
|
end
|
@@ -544,7 +546,7 @@ SKEEM
|
|
544
546
|
compare_to_predicted(checks)
|
545
547
|
end
|
546
548
|
|
547
|
-
|
549
|
+
it 'should implement the null? procedure' do
|
548
550
|
checks = [
|
549
551
|
['(null? #f)', false],
|
550
552
|
['(null? 1)', false],
|
@@ -591,7 +593,7 @@ SKEEM
|
|
591
593
|
example = "(cons '(a b) 'c)" # => ((a b) . c)
|
592
594
|
result = subject.run(example)
|
593
595
|
expect(result.car).to be_kind_of(SkmPair)
|
594
|
-
expect(result.car.to_a).to eq([
|
596
|
+
expect(result.car.to_a).to eq(%w[a b])
|
595
597
|
expect(result.cdr).to be_kind_of(SkmIdentifier)
|
596
598
|
expect(result.cdr).to eq('c')
|
597
599
|
end
|
@@ -616,7 +618,7 @@ SKEEM
|
|
616
618
|
result = subject.run(example)
|
617
619
|
expect(result).to be_list
|
618
620
|
expect(result.length).to eq(3)
|
619
|
-
expect(result.to_a).to eq([
|
621
|
+
expect(result.to_a).to eq(%w[b c d])
|
620
622
|
|
621
623
|
expect_expr("(cdr '(1 . 2))").to eq(2)
|
622
624
|
|
@@ -624,29 +626,37 @@ SKEEM
|
|
624
626
|
expect { subject.run(example) }.to raise_error(StandardError)
|
625
627
|
end
|
626
628
|
|
629
|
+
it 'should implement the length procedure' do
|
630
|
+
example = '(make-list 2 3)'
|
631
|
+
result = subject.run(example)
|
632
|
+
expect(result).to be_list
|
633
|
+
expect(result.length).to eq(2)
|
634
|
+
expect(result.to_a).to eq([3, 3])
|
635
|
+
end
|
636
|
+
|
627
637
|
it 'should implement the length procedure' do
|
628
638
|
checks = [
|
629
639
|
["(length '())", 0],
|
630
640
|
["(length '(1))", 1],
|
631
641
|
["(length '(1 2))", 2],
|
632
642
|
["(length '(1 2 3))", 3],
|
633
|
-
|
643
|
+
["(length '(a (b) (c d e)))", 3]
|
634
644
|
]
|
635
645
|
compare_to_predicted(checks)
|
636
646
|
end
|
637
647
|
|
638
648
|
it 'should implement the append procedure' do
|
639
649
|
checks = [
|
640
|
-
["(append '(a b c) '())", array2list_ids([
|
641
|
-
["(append '() '(a b c))", array2list_ids([
|
642
|
-
["(append '(x) '(y))", array2list_ids([
|
643
|
-
["(append '(a) '(b c d))", array2list_ids([
|
644
|
-
["(append '(a b) '(c d))", array2list_ids([
|
645
|
-
["(append '(a b) '(c) 'd)", array2list_ids([
|
650
|
+
["(append '(a b c) '())", array2list_ids(%w[a b c])],
|
651
|
+
["(append '() '(a b c))", array2list_ids(%w[a b c])],
|
652
|
+
["(append '(x) '(y))", array2list_ids(%w[x y])],
|
653
|
+
["(append '(a) '(b c d))", array2list_ids(%w[a b c d])],
|
654
|
+
["(append '(a b) '(c d))", array2list_ids(%w[a b c d])],
|
655
|
+
["(append '(a b) '(c) 'd)", array2list_ids(%w[a b c d])],
|
646
656
|
["(append '(a (b)) '((c)))", [SkmIdentifier.create('a'),
|
647
657
|
SkmPair.create_from_a(array2list_ids(['b'])),
|
648
658
|
SkmPair.create_from_a(array2list_ids(['c']))]],
|
649
|
-
[
|
659
|
+
["(append '() 'a)", SkmIdentifier.create('a')]
|
650
660
|
]
|
651
661
|
compare_to_predicted(checks) do |result, expectation|
|
652
662
|
if result.kind_of?(SkmPair)
|
@@ -659,18 +669,18 @@ SKEEM
|
|
659
669
|
|
660
670
|
it 'should implement the procedure for an improper list' do
|
661
671
|
result = subject.run("(append '(a b) '(c . d))")
|
662
|
-
expect(result.car).to eq(
|
663
|
-
expect(result.cdr.car).to eq(
|
664
|
-
expect(result.cdr.cdr.car).to eq(
|
665
|
-
expect(result.cdr.cdr.cdr).to eq(
|
672
|
+
expect(result.car).to eq(SkmIdentifier.create('a'))
|
673
|
+
expect(result.cdr.car).to eq(SkmIdentifier.create('b'))
|
674
|
+
expect(result.cdr.cdr.car).to eq(SkmIdentifier.create('c'))
|
675
|
+
expect(result.cdr.cdr.cdr).to eq(SkmIdentifier.create('d'))
|
666
676
|
end
|
667
677
|
|
668
678
|
|
669
679
|
it 'should implement the reverse procedure' do
|
670
680
|
checks = [
|
671
681
|
["(reverse '())", SkmEmptyList.instance],
|
672
|
-
["(reverse '(a b c))", array2list_ids([
|
673
|
-
["(reverse '((a) b c))", array2list_ids([
|
682
|
+
["(reverse '(a b c))", array2list_ids(%w[c b a])],
|
683
|
+
["(reverse '((a) b c))", array2list_ids(%w[c b]) << SkmPair.new(SkmIdentifier.create('a'), nil)]
|
674
684
|
]
|
675
685
|
compare_to_predicted(checks) do |result, expectation|
|
676
686
|
if result.kind_of?(SkmPair)
|
@@ -684,7 +694,7 @@ SKEEM
|
|
684
694
|
it 'should implement the list->vector procedure' do
|
685
695
|
checks = [
|
686
696
|
["(list->vector '())", []],
|
687
|
-
["(list->vector '(a b c))", [
|
697
|
+
["(list->vector '(a b c))", %w[a b c]]
|
688
698
|
]
|
689
699
|
compare_to_predicted(checks) do |result, expectation|
|
690
700
|
expect(result.to_a).to eq(expectation)
|
@@ -692,7 +702,7 @@ SKEEM
|
|
692
702
|
end
|
693
703
|
|
694
704
|
it 'should implement the set-car! procedure' do
|
695
|
-
source
|
705
|
+
source = <<-SKEEM
|
696
706
|
(define x '(a b c))
|
697
707
|
(set-car! x 1)
|
698
708
|
x
|
@@ -702,7 +712,7 @@ SKEEM
|
|
702
712
|
end
|
703
713
|
|
704
714
|
it 'should implement the set-cdr! procedure' do
|
705
|
-
source
|
715
|
+
source = <<-SKEEM
|
706
716
|
(define x '(a b c))
|
707
717
|
(set-cdr! x 1)
|
708
718
|
x
|
@@ -736,13 +746,13 @@ SKEEM
|
|
736
746
|
it 'should implement the list-copy procedure' do
|
737
747
|
checks = [
|
738
748
|
["(list-copy '())", []],
|
739
|
-
["(list-copy '(a b c))", [
|
749
|
+
["(list-copy '(a b c))", %w[a b c]]
|
740
750
|
]
|
741
751
|
compare_to_predicted(checks) do |result, expectation|
|
742
752
|
expect(result.to_a).to eq(expectation)
|
743
753
|
end
|
744
754
|
|
745
|
-
source
|
755
|
+
source = <<-SKEEM
|
746
756
|
(define a '(1 8 2 8)) ; a may be immutable
|
747
757
|
(define b (list-copy a))
|
748
758
|
(set-car! b 3) ; b is mutable
|
@@ -886,7 +896,7 @@ SKEEM
|
|
886
896
|
checks = [
|
887
897
|
['(vector-length (make-vector 0))', 0],
|
888
898
|
["(vector-length (make-vector 0 'a))", 0],
|
889
|
-
["(equal? (make-vector 5 'a) '#(a a a a a))", true]
|
899
|
+
["(equal? (make-vector 5 'a) '#(a a a a a))", true]
|
890
900
|
]
|
891
901
|
compare_to_predicted(checks)
|
892
902
|
end
|
@@ -899,21 +909,21 @@ SKEEM
|
|
899
909
|
end
|
900
910
|
|
901
911
|
it 'should implement the vector-set! procedure' do
|
902
|
-
source
|
912
|
+
source = <<-SKEEM
|
903
913
|
(let
|
904
914
|
((vec (vector 0 '(2 2 2 2) "Anna")))
|
905
915
|
(vector-set! vec 1 '("Sue" "Sue"))
|
906
916
|
vec)
|
907
917
|
SKEEM
|
908
|
-
#(0 ("Sue" "Sue") "Anna")
|
918
|
+
# (0 ("Sue" "Sue") "Anna")
|
909
919
|
result = subject.run(source)
|
910
920
|
expect(result).to be_kind_of(SkmVector)
|
911
|
-
expectation = [SkmInteger.create(0),
|
912
|
-
SkmPair.new(SkmString.create(
|
913
|
-
SkmString.create(
|
921
|
+
expectation = [SkmInteger.create(0),
|
922
|
+
SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
|
923
|
+
SkmString.create('Anna')]
|
914
924
|
expect(result).to eq(expectation)
|
915
925
|
|
916
|
-
source
|
926
|
+
source = <<-SKEEM
|
917
927
|
(let (
|
918
928
|
(v (vector 'a 'b 'c 'd 'e)))
|
919
929
|
(vector-set! v 2 'x)
|
@@ -921,13 +931,13 @@ SKEEM
|
|
921
931
|
SKEEM
|
922
932
|
result = subject.run(source)
|
923
933
|
expect(result).to be_kind_of(SkmVector)
|
924
|
-
expect(result).to eq(array2list_ids([
|
934
|
+
expect(result).to eq(array2list_ids(%w[a b x d e]))
|
925
935
|
end
|
926
936
|
|
927
937
|
it 'should implement the vector->list procedure' do
|
928
938
|
checks = [
|
929
|
-
[
|
930
|
-
["(vector->list '#(a b c))", [
|
939
|
+
['(vector->list #())', []],
|
940
|
+
["(vector->list '#(a b c))", %w[a b c]]
|
931
941
|
]
|
932
942
|
compare_to_predicted(checks) do |result, expectation|
|
933
943
|
expect(result.to_a).to eq(expectation)
|
@@ -938,9 +948,9 @@ SKEEM
|
|
938
948
|
context 'Control procedures:' do
|
939
949
|
it 'should implement the procedure? predicate' do
|
940
950
|
checks = [
|
941
|
-
[
|
951
|
+
['(procedure? car)', true],
|
942
952
|
["(procedure? 'car)", false],
|
943
|
-
[
|
953
|
+
['(procedure? (lambda (x) (* x x)))', true]
|
944
954
|
# ["(procedure? '(lambda (x) (* x x)))", false] # Parse fail: non-standard syntax
|
945
955
|
]
|
946
956
|
compare_to_predicted(checks)
|
@@ -955,7 +965,7 @@ SKEEM
|
|
955
965
|
|
956
966
|
it 'should implement the map procedure' do
|
957
967
|
checks = [
|
958
|
-
["(map car '((a b) (d e) (g h)))", [
|
968
|
+
["(map car '((a b) (d e) (g h)))", %w[a d g]],
|
959
969
|
["(map + '(1 2 3) '(4 5 6 7))", [5, 7, 9]]
|
960
970
|
]
|
961
971
|
compare_to_predicted(checks) do |result, expectation|
|
@@ -965,16 +975,23 @@ SKEEM
|
|
965
975
|
end # context
|
966
976
|
|
967
977
|
context 'IO procedures:' do
|
968
|
-
it 'should implement the
|
978
|
+
it 'should implement the display procedure' do
|
969
979
|
default_stdout = $stdout
|
970
|
-
$stdout = StringIO.new
|
971
|
-
subject.run('(
|
972
|
-
expect($stdout.string).to
|
980
|
+
$stdout = StringIO.new
|
981
|
+
subject.run('(display "Hello")')
|
982
|
+
expect($stdout.string).to eq('Hello')
|
973
983
|
$stdout = default_stdout
|
974
984
|
end
|
975
985
|
end # context
|
976
986
|
|
977
987
|
context 'Miscellaneous procedures' do
|
988
|
+
it 'should raise an exception with given error message' do
|
989
|
+
source = '(error "This is an error message")'
|
990
|
+
err = SkmError
|
991
|
+
msg = 'This is an error message'
|
992
|
+
expect { subject.run(source) }.to raise_error(err, msg)
|
993
|
+
end
|
994
|
+
|
978
995
|
it 'should return true when an assertion succeeds' do
|
979
996
|
source = <<-SKEEM
|
980
997
|
(define x 2)
|
@@ -993,9 +1010,9 @@ SKEEM
|
|
993
1010
|
err = StandardError
|
994
1011
|
msg1 = 'Error: assertion failed on line 3, column 4'
|
995
1012
|
msg2 = 'with <Skeem::SkmBoolean: false>'
|
996
|
-
expect { subject.run(source) }.to raise_error(err, msg1
|
1013
|
+
expect { subject.run(source) }.to raise_error(err, "#{msg1}, #{msg2}")
|
997
1014
|
end
|
998
1015
|
end # context
|
999
1016
|
end # describe
|
1000
1017
|
end # module
|
1001
|
-
end # module
|
1018
|
+
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative '../../spec_helper' # Use the RSpec framework
|
2
4
|
|
3
5
|
# Load the class under test
|
@@ -9,8 +11,8 @@ module Skeem
|
|
9
11
|
let(:nullary) { SkmArity.new(0, 0) }
|
10
12
|
let(:unary) { SkmArity.new(1, 1) }
|
11
13
|
let(:binary) { SkmArity.new(2, 2) }
|
12
|
-
let(:zero_or_more) {SkmArity.new(0, '*') }
|
13
|
-
let(:one_or_more) {SkmArity.new(1, '*') }
|
14
|
+
let(:zero_or_more) { SkmArity.new(0, '*') }
|
15
|
+
let(:one_or_more) { SkmArity.new(1, '*') }
|
14
16
|
let(:newline_code) do
|
15
17
|
->(_runtime) { "\n" }
|
16
18
|
end
|
@@ -49,7 +51,7 @@ module Skeem
|
|
49
51
|
end
|
50
52
|
|
51
53
|
it 'should complain if third argument is not a lambda' do
|
52
|
-
kode =
|
54
|
+
kode = proc { puts '' }
|
53
55
|
|
54
56
|
err = StandardError
|
55
57
|
err_msg = "Primitive procedure 'newline' must be implemented with a Ruby lambda."
|
@@ -57,7 +59,7 @@ module Skeem
|
|
57
59
|
end
|
58
60
|
|
59
61
|
it 'should complain if third argument is a nullary lambda' do
|
60
|
-
kode = ->
|
62
|
+
kode = -> { puts '' } # Missing slot for Runtime object
|
61
63
|
|
62
64
|
err = StandardError
|
63
65
|
err_msg = "Primitive procedure 'newline' lambda takes no parameter."
|
@@ -68,10 +70,10 @@ module Skeem
|
|
68
70
|
err = StandardError
|
69
71
|
msg1 = "Discrepancy in primitive procedure 'cube' "
|
70
72
|
|
71
|
-
msg2 =
|
73
|
+
msg2 = 'between arity (0) + 1 and parameter count of lambda 2.'
|
72
74
|
expect { PrimitiveProcedure.new('cube', nullary, cube) }.to raise_error(err, msg1 + msg2)
|
73
75
|
|
74
|
-
msg2 =
|
76
|
+
msg2 = 'between arity (2) + 1 and parameter count of lambda 2.'
|
75
77
|
expect { PrimitiveProcedure.new('cube', binary, cube) }.to raise_error(err, msg1 + msg2)
|
76
78
|
|
77
79
|
# Nasty; this discrepancy isn't detected
|
@@ -79,7 +81,7 @@ module Skeem
|
|
79
81
|
|
80
82
|
expect { PrimitiveProcedure.new('cube', unary, cube) }.not_to raise_error
|
81
83
|
|
82
|
-
msg2 =
|
84
|
+
msg2 = 'between arity (1) + 2 and parameter count of lambda 2.'
|
83
85
|
expect { PrimitiveProcedure.new('cube', one_or_more, cube) }.to raise_error(err, msg1 + msg2)
|
84
86
|
end
|
85
87
|
end # context
|
@@ -109,7 +111,7 @@ module Skeem
|
|
109
111
|
ms2 = ' (required at least 1, got 0)'
|
110
112
|
expect { pproc.call(rtime, []) }.to raise_error(err, ms1 + ms2)
|
111
113
|
|
112
|
-
too_much = [
|
114
|
+
too_much = %w[foo bar]
|
113
115
|
err = StandardError
|
114
116
|
ms1 = 'Wrong number of arguments for #<Procedure cube>'
|
115
117
|
ms2 = ' (required at least 1, got 2)'
|
@@ -129,7 +131,7 @@ module Skeem
|
|
129
131
|
ms2 = ' (required at least 2, got 1)'
|
130
132
|
expect { pproc.call(rtime, too_few) }.to raise_error(err, ms1 + ms2)
|
131
133
|
|
132
|
-
too_much = [
|
134
|
+
too_much = %w[foo bar quux]
|
133
135
|
err = StandardError
|
134
136
|
ms1 = 'Wrong number of arguments for #<Procedure sum>'
|
135
137
|
ms2 = ' (required at least 2, got 3)'
|
@@ -146,11 +148,11 @@ module Skeem
|
|
146
148
|
no_arg = []
|
147
149
|
expect(pproc.call(rtime, no_arg)).to eq(0)
|
148
150
|
|
149
|
-
many = [SkmString.create('foo'), SkmString.create('bar'),
|
151
|
+
many = [SkmString.create('foo'), SkmString.create('bar'),
|
150
152
|
SkmString.create('quux')]
|
151
|
-
expect(
|
153
|
+
expect(pproc.call(rtime, many)).to eq(3)
|
152
154
|
end
|
153
155
|
end # context
|
154
156
|
end # describe
|
155
157
|
end # module
|
156
|
-
end # module
|
158
|
+
end # module
|
data/spec/skeem/runtime_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
2
4
|
require_relative '../../lib/skeem/datum_dsl'
|
3
5
|
require_relative '../../lib/skeem/s_expr_nodes'
|
@@ -8,7 +10,7 @@ require_relative '../../lib/skeem/runtime' # Load the class under test
|
|
8
10
|
module Skeem
|
9
11
|
describe Runtime do
|
10
12
|
include DatumDSL
|
11
|
-
|
13
|
+
|
12
14
|
let(:some_env) { SkmFrame.new }
|
13
15
|
subject { Runtime.new(some_env) }
|
14
16
|
|
@@ -20,7 +22,7 @@ module Skeem
|
|
20
22
|
it 'should know the environment' do
|
21
23
|
expect(subject.environment).to eq(some_env)
|
22
24
|
end
|
23
|
-
|
25
|
+
|
24
26
|
it 'should have an empty call stack' do
|
25
27
|
expect(subject.call_stack).to be_empty
|
26
28
|
end
|
@@ -42,10 +44,10 @@ module Skeem
|
|
42
44
|
expect(subject.include?('dummy')).to be_truthy
|
43
45
|
end
|
44
46
|
end # context
|
45
|
-
|
47
|
+
|
46
48
|
context 'Evaluation:' do
|
47
49
|
include Primitive::PrimitiveBuilder
|
48
|
-
|
50
|
+
|
49
51
|
# it 'should evaluate a given entry' do
|
50
52
|
# entry = integer(3)
|
51
53
|
# result = double('fake-procedure')
|
@@ -54,21 +56,21 @@ module Skeem
|
|
54
56
|
# subject.define('three', entry)
|
55
57
|
# expect(subject.evaluate('three')).to eq(3)
|
56
58
|
# end
|
57
|
-
|
59
|
+
|
58
60
|
it 'should evaluate a given list' do
|
59
61
|
add_primitives(subject)
|
60
62
|
sum = list([identifier('+'), 3, 4])
|
61
|
-
|
63
|
+
|
62
64
|
expect(subject.evaluate_form(sum)).to eq(7)
|
63
65
|
end
|
64
66
|
end # context
|
65
|
-
|
67
|
+
|
66
68
|
context 'Environment nesting:' do
|
67
69
|
it 'should add nested environment' do
|
68
70
|
expect(subject.depth).to eq(1)
|
69
71
|
env_before = subject.environment
|
70
72
|
subject.nest
|
71
|
-
|
73
|
+
|
72
74
|
expect(subject.environment).not_to eq(env_before)
|
73
75
|
expect(subject.environment.parent).to eq(env_before)
|
74
76
|
expect(subject.depth).to eq(2)
|
@@ -79,37 +81,37 @@ module Skeem
|
|
79
81
|
subject.nest
|
80
82
|
parent_before = subject.environment.parent
|
81
83
|
expect(subject.depth).to eq(2)
|
82
|
-
|
84
|
+
|
83
85
|
subject.unnest
|
84
86
|
expect(subject.environment).to eq(parent_before)
|
85
87
|
expect(subject.depth).to eq(1)
|
86
88
|
end
|
87
89
|
end # context
|
88
|
-
|
90
|
+
|
89
91
|
context 'Call stack operations:' do
|
90
92
|
let(:sample_call) do
|
91
93
|
pos = double('fake-position')
|
92
|
-
ProcedureCall.new(pos, identifier('boolean?'), [integer(42)])
|
94
|
+
ProcedureCall.new(pos, identifier('boolean?'), [integer(42)])
|
93
95
|
end
|
94
|
-
|
96
|
+
|
95
97
|
it 'should push a call to the stack call' do
|
96
98
|
expect { subject.push_call(sample_call) }.not_to raise_error
|
97
|
-
expect(subject.call_stack.size).
|
99
|
+
expect(subject.call_stack.size).to eq(1)
|
98
100
|
expect(subject.caller).to eq(sample_call)
|
99
|
-
|
101
|
+
|
100
102
|
subject.push_call(sample_call.clone)
|
101
|
-
expect(subject.call_stack.size).
|
103
|
+
expect(subject.call_stack.size).to eq(2)
|
102
104
|
end
|
103
105
|
|
104
106
|
it 'should pop a call from the call stack' do
|
105
107
|
subject.push_call(sample_call)
|
106
108
|
expect { subject.pop_call }.not_to raise_error
|
107
109
|
expect(subject.call_stack).to be_empty
|
108
|
-
|
110
|
+
|
109
111
|
err = StandardError
|
110
112
|
msg = 'Skeem call stack empty!'
|
111
113
|
expect { subject.pop_call }.to raise_error(err, msg)
|
112
114
|
end
|
113
|
-
end # context
|
115
|
+
end # context
|
114
116
|
end # describe
|
115
|
-
end # module
|
117
|
+
end # module
|