skeem 0.2.14 → 0.2.18
Sign up to get free protection for your applications and to get access to all the features.
- 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
|