skeem 0.2.15 → 0.2.19
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 +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
|