skeem 0.2.15 → 0.2.19
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 +26 -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/datum_dsl.rb +40 -30
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +77 -54
- data/lib/skeem/interpreter.rb +9 -7
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +130 -122
- data/lib/skeem/primitive/primitive_procedure.rb +23 -25
- data/lib/skeem/runtime.rb +17 -15
- data/lib/skeem/s_expr_builder.rb +39 -147
- 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/tokenizer.rb +40 -30
- data/lib/skeem/version.rb +3 -1
- data/lib/skeem.rb +2 -0
- data/skeem.gemspec +7 -5
- 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 +76 -46
- data/spec/skeem/lambda_spec.rb +13 -11
- data/spec/skeem/parser_spec.rb +23 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +55 -46
- 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 +13 -9
@@ -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,21 +618,21 @@ 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
|
|
623
625
|
example = "(cdr '())" # => error
|
624
626
|
expect { subject.run(example) }.to raise_error(StandardError)
|
625
627
|
end
|
626
|
-
|
628
|
+
|
627
629
|
it 'should implement the length procedure' do
|
628
630
|
example = '(make-list 2 3)'
|
629
631
|
result = subject.run(example)
|
630
632
|
expect(result).to be_list
|
631
633
|
expect(result.length).to eq(2)
|
632
634
|
expect(result.to_a).to eq([3, 3])
|
633
|
-
end
|
635
|
+
end
|
634
636
|
|
635
637
|
it 'should implement the length procedure' do
|
636
638
|
checks = [
|
@@ -638,23 +640,23 @@ SKEEM
|
|
638
640
|
["(length '(1))", 1],
|
639
641
|
["(length '(1 2))", 2],
|
640
642
|
["(length '(1 2 3))", 3],
|
641
|
-
|
643
|
+
["(length '(a (b) (c d e)))", 3]
|
642
644
|
]
|
643
645
|
compare_to_predicted(checks)
|
644
646
|
end
|
645
647
|
|
646
648
|
it 'should implement the append procedure' do
|
647
649
|
checks = [
|
648
|
-
["(append '(a b c) '())", array2list_ids([
|
649
|
-
["(append '() '(a b c))", array2list_ids([
|
650
|
-
["(append '(x) '(y))", array2list_ids([
|
651
|
-
["(append '(a) '(b c d))", array2list_ids([
|
652
|
-
["(append '(a b) '(c d))", array2list_ids([
|
653
|
-
["(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])],
|
654
656
|
["(append '(a (b)) '((c)))", [SkmIdentifier.create('a'),
|
655
657
|
SkmPair.create_from_a(array2list_ids(['b'])),
|
656
658
|
SkmPair.create_from_a(array2list_ids(['c']))]],
|
657
|
-
[
|
659
|
+
["(append '() 'a)", SkmIdentifier.create('a')]
|
658
660
|
]
|
659
661
|
compare_to_predicted(checks) do |result, expectation|
|
660
662
|
if result.kind_of?(SkmPair)
|
@@ -667,18 +669,18 @@ SKEEM
|
|
667
669
|
|
668
670
|
it 'should implement the procedure for an improper list' do
|
669
671
|
result = subject.run("(append '(a b) '(c . d))")
|
670
|
-
expect(result.car).to eq(
|
671
|
-
expect(result.cdr.car).to eq(
|
672
|
-
expect(result.cdr.cdr.car).to eq(
|
673
|
-
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'))
|
674
676
|
end
|
675
677
|
|
676
678
|
|
677
679
|
it 'should implement the reverse procedure' do
|
678
680
|
checks = [
|
679
681
|
["(reverse '())", SkmEmptyList.instance],
|
680
|
-
["(reverse '(a b c))", array2list_ids([
|
681
|
-
["(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)]
|
682
684
|
]
|
683
685
|
compare_to_predicted(checks) do |result, expectation|
|
684
686
|
if result.kind_of?(SkmPair)
|
@@ -692,7 +694,7 @@ SKEEM
|
|
692
694
|
it 'should implement the list->vector procedure' do
|
693
695
|
checks = [
|
694
696
|
["(list->vector '())", []],
|
695
|
-
["(list->vector '(a b c))", [
|
697
|
+
["(list->vector '(a b c))", %w[a b c]]
|
696
698
|
]
|
697
699
|
compare_to_predicted(checks) do |result, expectation|
|
698
700
|
expect(result.to_a).to eq(expectation)
|
@@ -700,7 +702,7 @@ SKEEM
|
|
700
702
|
end
|
701
703
|
|
702
704
|
it 'should implement the set-car! procedure' do
|
703
|
-
source
|
705
|
+
source = <<-SKEEM
|
704
706
|
(define x '(a b c))
|
705
707
|
(set-car! x 1)
|
706
708
|
x
|
@@ -710,7 +712,7 @@ SKEEM
|
|
710
712
|
end
|
711
713
|
|
712
714
|
it 'should implement the set-cdr! procedure' do
|
713
|
-
source
|
715
|
+
source = <<-SKEEM
|
714
716
|
(define x '(a b c))
|
715
717
|
(set-cdr! x 1)
|
716
718
|
x
|
@@ -744,13 +746,13 @@ SKEEM
|
|
744
746
|
it 'should implement the list-copy procedure' do
|
745
747
|
checks = [
|
746
748
|
["(list-copy '())", []],
|
747
|
-
["(list-copy '(a b c))", [
|
749
|
+
["(list-copy '(a b c))", %w[a b c]]
|
748
750
|
]
|
749
751
|
compare_to_predicted(checks) do |result, expectation|
|
750
752
|
expect(result.to_a).to eq(expectation)
|
751
753
|
end
|
752
754
|
|
753
|
-
source
|
755
|
+
source = <<-SKEEM
|
754
756
|
(define a '(1 8 2 8)) ; a may be immutable
|
755
757
|
(define b (list-copy a))
|
756
758
|
(set-car! b 3) ; b is mutable
|
@@ -894,7 +896,7 @@ SKEEM
|
|
894
896
|
checks = [
|
895
897
|
['(vector-length (make-vector 0))', 0],
|
896
898
|
["(vector-length (make-vector 0 'a))", 0],
|
897
|
-
["(equal? (make-vector 5 'a) '#(a a a a a))", true]
|
899
|
+
["(equal? (make-vector 5 'a) '#(a a a a a))", true]
|
898
900
|
]
|
899
901
|
compare_to_predicted(checks)
|
900
902
|
end
|
@@ -907,21 +909,21 @@ SKEEM
|
|
907
909
|
end
|
908
910
|
|
909
911
|
it 'should implement the vector-set! procedure' do
|
910
|
-
source
|
912
|
+
source = <<-SKEEM
|
911
913
|
(let
|
912
914
|
((vec (vector 0 '(2 2 2 2) "Anna")))
|
913
915
|
(vector-set! vec 1 '("Sue" "Sue"))
|
914
916
|
vec)
|
915
917
|
SKEEM
|
916
|
-
#(0 ("Sue" "Sue") "Anna")
|
918
|
+
# (0 ("Sue" "Sue") "Anna")
|
917
919
|
result = subject.run(source)
|
918
920
|
expect(result).to be_kind_of(SkmVector)
|
919
921
|
expectation = [SkmInteger.create(0),
|
920
|
-
SkmPair.new(SkmString.create(
|
921
|
-
SkmString.create(
|
922
|
+
SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
|
923
|
+
SkmString.create('Anna')]
|
922
924
|
expect(result).to eq(expectation)
|
923
925
|
|
924
|
-
source
|
926
|
+
source = <<-SKEEM
|
925
927
|
(let (
|
926
928
|
(v (vector 'a 'b 'c 'd 'e)))
|
927
929
|
(vector-set! v 2 'x)
|
@@ -929,13 +931,13 @@ SKEEM
|
|
929
931
|
SKEEM
|
930
932
|
result = subject.run(source)
|
931
933
|
expect(result).to be_kind_of(SkmVector)
|
932
|
-
expect(result).to eq(array2list_ids([
|
934
|
+
expect(result).to eq(array2list_ids(%w[a b x d e]))
|
933
935
|
end
|
934
936
|
|
935
937
|
it 'should implement the vector->list procedure' do
|
936
938
|
checks = [
|
937
|
-
[
|
938
|
-
["(vector->list '#(a b c))", [
|
939
|
+
['(vector->list #())', []],
|
940
|
+
["(vector->list '#(a b c))", %w[a b c]]
|
939
941
|
]
|
940
942
|
compare_to_predicted(checks) do |result, expectation|
|
941
943
|
expect(result.to_a).to eq(expectation)
|
@@ -946,9 +948,9 @@ SKEEM
|
|
946
948
|
context 'Control procedures:' do
|
947
949
|
it 'should implement the procedure? predicate' do
|
948
950
|
checks = [
|
949
|
-
[
|
951
|
+
['(procedure? car)', true],
|
950
952
|
["(procedure? 'car)", false],
|
951
|
-
[
|
953
|
+
['(procedure? (lambda (x) (* x x)))', true]
|
952
954
|
# ["(procedure? '(lambda (x) (* x x)))", false] # Parse fail: non-standard syntax
|
953
955
|
]
|
954
956
|
compare_to_predicted(checks)
|
@@ -963,7 +965,7 @@ SKEEM
|
|
963
965
|
|
964
966
|
it 'should implement the map procedure' do
|
965
967
|
checks = [
|
966
|
-
["(map car '((a b) (d e) (g h)))", [
|
968
|
+
["(map car '((a b) (d e) (g h)))", %w[a d g]],
|
967
969
|
["(map + '(1 2 3) '(4 5 6 7))", [5, 7, 9]]
|
968
970
|
]
|
969
971
|
compare_to_predicted(checks) do |result, expectation|
|
@@ -975,7 +977,7 @@ SKEEM
|
|
975
977
|
context 'IO procedures:' do
|
976
978
|
it 'should implement the display procedure' do
|
977
979
|
default_stdout = $stdout
|
978
|
-
$stdout = StringIO.new
|
980
|
+
$stdout = StringIO.new
|
979
981
|
subject.run('(display "Hello")')
|
980
982
|
expect($stdout.string).to eq('Hello')
|
981
983
|
$stdout = default_stdout
|
@@ -983,6 +985,13 @@ SKEEM
|
|
983
985
|
end # context
|
984
986
|
|
985
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
|
+
|
986
995
|
it 'should return true when an assertion succeeds' do
|
987
996
|
source = <<-SKEEM
|
988
997
|
(define x 2)
|
@@ -1001,9 +1010,9 @@ SKEEM
|
|
1001
1010
|
err = StandardError
|
1002
1011
|
msg1 = 'Error: assertion failed on line 3, column 4'
|
1003
1012
|
msg2 = 'with <Skeem::SkmBoolean: false>'
|
1004
|
-
expect { subject.run(source) }.to raise_error(err, msg1
|
1013
|
+
expect { subject.run(source) }.to raise_error(err, "#{msg1}, #{msg2}")
|
1005
1014
|
end
|
1006
1015
|
end # context
|
1007
1016
|
end # describe
|
1008
1017
|
end # module
|
1009
|
-
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
|