frepl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Frepl::Function do
4
+ let(:simple_function) do
5
+ Frepl::Function.new([
6
+ 'integer function m(x, y)',
7
+ 'integer, intent(in) :: x, y',
8
+ 'm = x + y',
9
+ 'end function m'])
10
+ end
11
+ context 'simple function' do
12
+ it 'extracts function name' do
13
+ expect(simple_function.name).to eq('m')
14
+ end
15
+ end
16
+
17
+ describe '#==' do
18
+
19
+ context 'when other is a `Function`' do
20
+
21
+ let(:other_same) do
22
+ Frepl::Function.new([
23
+ 'integer function m(x, y)',
24
+ 'integer, intent(in) :: x, y',
25
+ 'm = x * y',
26
+ 'end function m'])
27
+ end
28
+
29
+ let(:other_diff) do
30
+ Frepl::Function.new([
31
+ 'integer function n(x, y)',
32
+ 'integer, intent(in) :: x, y',
33
+ 'm = x + y',
34
+ 'end function m'])
35
+ end
36
+
37
+ it 'compares by function name' do
38
+ expect(simple_function).to eq(other_same)
39
+ expect(simple_function).not_to eq(other_diff)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Frepl::MultiDeclaration do
4
+ context 'multi declaration' do
5
+ let(:d) { Frepl::MultiDeclaration.new('integer a, b') }
6
+
7
+ it 'extracts variable names' do
8
+ expect(d.variable_names).to eq(['a', 'b'])
9
+ end
10
+ end
11
+
12
+ context 'multi declaration with assignment' do
13
+ let(:d) { Frepl::MultiDeclaration.new('integer :: a = 1, b = 2') }
14
+
15
+ it 'extracts variable names' do
16
+ expect(d.variable_names).to eq(['a', 'b'])
17
+ end
18
+
19
+ it 'generates declarations with the right data' do
20
+ expect(d.declarations.first.variable_name).to eq('a')
21
+ expect(d.declarations.first.assigned_value).to eq('1')
22
+ end
23
+ end
24
+
25
+ context 'multiple F2003 array declarations' do
26
+ let(:d) { Frepl::MultiDeclaration.new('integer, dimension(2) :: a = [1,2], b = [2,3]') }
27
+
28
+ it 'extracts variable names' do
29
+ expect(d.variable_names).to eq(['a', 'b'])
30
+ end
31
+ end
32
+
33
+ context 'declarations without assignments, and with' do
34
+ let(:d) { Frepl::MultiDeclaration.new('integer, dimension(2) :: a, b = [2,3]') }
35
+
36
+ it 'extracts variable names' do
37
+ expect(d.variable_names).to eq(['a', 'b'])
38
+ end
39
+
40
+ it 'correctly generates declaration types' do
41
+ expect(d.declarations.map(&:type)).to eq(['integer', 'integer'])
42
+ end
43
+
44
+ it 'correctly generates declaration assignments' do
45
+ d1, d2 = d.declarations
46
+ expect(d1.variable_name).to eq('a')
47
+ expect(d1.assigned_value).to be_nil
48
+ expect(d1.output).to eq("integer, dimension(2) :: a\n")
49
+ expect(d2.variable_name).to eq('b')
50
+ expect(d2.assigned_value).to eq('[2,3]')
51
+ expect(d2.output).to eq("integer, dimension(2) :: b=[2,3]\n")
52
+ end
53
+ end
54
+
55
+ context 'declarations with assignments, and without' do
56
+ let(:d) { Frepl::MultiDeclaration.new('integer :: a = 1, b, c') }
57
+
58
+ it 'extracts variable names' do
59
+ expect(d.variable_names).to eq(['a', 'b', 'c'])
60
+ end
61
+
62
+ it 'correctly generates declaration types' do
63
+ expect(d.declarations.map(&:type)).to eq(['integer', 'integer', 'integer'])
64
+ end
65
+
66
+ it 'correctly generates declaration assignments' do
67
+ d1, d2, d3 = d.declarations
68
+ expect(d1.variable_name).to eq('a')
69
+ expect(d1.assigned_value).to eq('1')
70
+ expect(d1.output).to eq("integer :: a=1\n")
71
+ expect(d2.variable_name).to eq('b')
72
+ expect(d2.assigned_value).to be_nil
73
+ expect(d2.output).to eq("integer :: b\n")
74
+ expect(d3.variable_name).to eq('c')
75
+ expect(d3.assigned_value).to be_nil
76
+ expect(d3.output).to eq("integer :: c\n")
77
+ end
78
+ end
79
+
80
+ context 'deferred shape pointer array' do
81
+ let(:d) { Frepl::MultiDeclaration.new('integer, dimension(:), pointer :: row, col') }
82
+
83
+ it 'extracts variable names' do
84
+ expect(d.variable_names).to eq(['row', 'col'])
85
+ end
86
+
87
+ it 'correctly generates declaration types' do
88
+ expect(d.declarations.map(&:type)).to eq(['integer', 'integer'])
89
+ end
90
+
91
+ it 'correctly generates declaration assignments' do
92
+ d1, d2 = d.declarations
93
+ expect(d1.variable_name).to eq('row')
94
+ expect(d1.assigned_value).to be_nil
95
+ expect(d1.output).to eq("integer, dimension(:), pointer :: row\n")
96
+ expect(d2.variable_name).to eq('col')
97
+ expect(d2.assigned_value).to be_nil
98
+ expect(d2.output).to eq("integer, dimension(:), pointer :: col\n")
99
+ end
100
+ end
101
+
102
+ context 'targetable arrays' do
103
+ let(:d) { Frepl::MultiDeclaration.new('integer, dimension(2), target :: a, b') }
104
+
105
+ it 'extracts variable names' do
106
+ expect(d.variable_names).to eq(['a', 'b'])
107
+ end
108
+
109
+ it 'correctly generates declaration types' do
110
+ expect(d.declarations.map(&:type)).to eq(['integer', 'integer'])
111
+ end
112
+
113
+ it 'correctly generates declaration assignments' do
114
+ d1, d2 = d.declarations
115
+ expect(d1.variable_name).to eq('a')
116
+ expect(d1.assigned_value).to be_nil
117
+ expect(d1.output).to eq("integer, dimension(2), target :: a\n")
118
+ expect(d2.variable_name).to eq('b')
119
+ expect(d2.assigned_value).to be_nil
120
+ expect(d2.output).to eq("integer, dimension(2), target :: b\n")
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Frepl::Subroutine do
4
+ let(:simple_subroutine) do
5
+ Frepl::Subroutine.new([
6
+ 'subroutine swap(x, y)',
7
+ 'integer, intent(in) :: x',
8
+ 'integer, intent(out) :: y',
9
+ 'y = x',
10
+ 'end subroutine swap'
11
+ ])
12
+ end
13
+ context 'simple subroutine' do
14
+ it 'extracts subroutine name' do
15
+ expect(simple_subroutine.name).to eq('swap')
16
+ end
17
+ end
18
+
19
+ describe '#==' do
20
+ context 'when other is a `Subroutine`' do
21
+ let(:other_same) do
22
+ Frepl::Subroutine.new([
23
+ 'subroutine swap(x, y)',
24
+ 'integer, intent(in) :: x',
25
+ 'integer, intent(out) :: y',
26
+ 'y = x',
27
+ 'end subroutine swap'
28
+ ])
29
+ end
30
+
31
+ let(:other_diff) do
32
+ Frepl::Subroutine.new([
33
+ 'subroutine swip(x, y)',
34
+ 'integer, intent(in) :: x',
35
+ 'integer, intent(out) :: y',
36
+ 'y = x',
37
+ ])
38
+ end
39
+
40
+ it 'compares by subroutine name' do
41
+ expect(simple_subroutine).to eq(other_same)
42
+ expect(simple_subroutine).not_to eq(other_diff)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,256 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Frepl do
4
+ let(:frepl) { Frepl::Main.new }
5
+ describe 'functional specs', type: :functional do
6
+ context 'basic program' do
7
+ it 'works' do
8
+ expect(Frepl).to receive(:output).with(" 1\n").twice
9
+ file = [
10
+ 'integer a',
11
+ 'a = 1',
12
+ 'write(*,*) a'
13
+ ]
14
+ frepl.run_file(file)
15
+ end
16
+ end
17
+
18
+ context 'declaring multiple variables on a single line' do
19
+ it 'works' do
20
+ expect(Frepl).to receive(:output).with(" 6\n")
21
+ file = [
22
+ 'integer :: a = 2, b = 4',
23
+ 'write(*,*) a + b'
24
+ ]
25
+ frepl.run_file(file)
26
+ end
27
+ end
28
+
29
+ context 'defining a function' do
30
+ it 'works' do
31
+ expect(Frepl).to receive(:output).with(" 12\n")
32
+ file = [
33
+ 'integer :: a = 8, b = 4',
34
+ 'integer function add(x, y)',
35
+ 'integer, intent(in) :: x, y',
36
+ 'add = x + y',
37
+ 'end function add',
38
+ 'write(*,*) add(a, b)'
39
+ ]
40
+ frepl.run_file(file)
41
+ end
42
+ end
43
+
44
+ context 'redefining the type of a variable' do
45
+ it 'works' do
46
+ expect(Frepl).to receive(:output).with(" 3\n")
47
+ expect(Frepl).to receive(:output).with(" 3.40000010 \n")
48
+ file = [
49
+ 'integer :: a = 8',
50
+ 'a = 3',
51
+ 'real :: a = 3.4',
52
+ 'write(*,*) a'
53
+ ]
54
+ frepl.run_file(file)
55
+ end
56
+ end
57
+
58
+ context 'redefining a scalar to vector' do
59
+ it 'works' do
60
+ expect(Frepl).to receive(:output).with(" 3\n")
61
+ expect(Frepl).to receive(:output).with(" 1 2\n")
62
+ file = [
63
+ 'integer :: a = 8',
64
+ 'a = 3',
65
+ 'integer, dimension(2) :: a = [1,2]',
66
+ 'write(*,*) a'
67
+ ]
68
+ frepl.run_file(file)
69
+ end
70
+ end
71
+
72
+ context 'redefining a function' do
73
+ it 'works' do
74
+ expect(Frepl).to receive(:output).with(" 1\n")
75
+ file = [
76
+ 'integer function m(x, y)',
77
+ 'integer, intent(in) :: x, y',
78
+ 'm = x + y',
79
+ 'end function m',
80
+ 'integer function m(x, y)',
81
+ 'integer, intent(in) :: x, y',
82
+ 'm = x - y',
83
+ 'end function m',
84
+ 'write(*,*) m(3, 2)'
85
+ ]
86
+ frepl.run_file(file)
87
+ end
88
+ end
89
+
90
+ context 'changing the kind of a real' do
91
+ it 'works' do
92
+ expect(Frepl).to receive(:output).with(match(/12\.\d{7}\s+/))
93
+ expect(Frepl).to receive(:output).with(match(/12\.\d{15}\s+/))
94
+ file = [
95
+ 'real(kind=4) :: a = 3.14',
96
+ 'write(*,*) a * 4',
97
+ 'real(kind=8) :: a = 3.14',
98
+ 'write(*,*) a * 4'
99
+ ]
100
+ frepl.run_file(file)
101
+ end
102
+ end
103
+
104
+ context 'redefining a subroutine' do
105
+ it 'works' do
106
+ # TODO shouldn't require this first expectation -- don't do IO
107
+ # unless last(current) execution is WRITE/PRINT or something
108
+ expect(Frepl).to receive(:output).with("")
109
+ expect(Frepl).to receive(:output).with(" 1\n")
110
+ file = [
111
+ 'integer :: a = 1, b = 1, c = 1',
112
+ 'subroutine swap(x, y)',
113
+ 'integer, intent(in) :: x',
114
+ 'integer, intent(out) :: y',
115
+ 'y = x',
116
+ 'end subroutine swap',
117
+ 'subroutine swap(x, y, z)',
118
+ 'integer, intent(in) :: x',
119
+ 'integer, intent(out) :: y, z',
120
+ 'y = x',
121
+ 'z = x',
122
+ 'end subroutine swap',
123
+ 'call swap(a, b, c)',
124
+ 'write(*,*) c'
125
+ ]
126
+ frepl.run_file(file)
127
+ end
128
+ end
129
+
130
+ context 'echoing a variable value' do
131
+ it 'works' do
132
+ expect(Frepl).to receive(:output).with(" 1\n").twice
133
+ file = [
134
+ 'integer a',
135
+ 'a = 1',
136
+ 'a'
137
+ ]
138
+ frepl.run_file(file)
139
+ end
140
+ end
141
+
142
+ context 'with an if statement' do
143
+ it 'works' do
144
+ expect(Frepl).to receive(:output).with(" 1\n")
145
+ file = [
146
+ 'logical :: check = .true.',
147
+ 'if (check .EQV. .TRUE.) then',
148
+ 'write(*,*) 1',
149
+ 'end if'
150
+ ]
151
+ frepl.run_file(file)
152
+ end
153
+ end
154
+
155
+ context 'with a do loop' do
156
+ it 'works' do
157
+ expect(Frepl).to receive(:output).with(" 1\n 2\n 3\n")
158
+ file = [
159
+ 'integer i',
160
+ 'do i = 1, 3 ',
161
+ 'write(*,*) i',
162
+ 'end do'
163
+ ]
164
+ frepl.run_file(file)
165
+ end
166
+ end
167
+
168
+ context 'with a derived type' do
169
+ it 'works' do
170
+ expect(Frepl).to receive(:output).with(" 3.40000010 \n")
171
+ expect(Frepl).to receive(:output).with(" 4.05000019 \n")
172
+ expect(Frepl).to receive(:output).with(" 3.40000010 4.05000019 \n")
173
+ file = [
174
+ 'type point',
175
+ 'real :: x, y',
176
+ 'end type point',
177
+ 'type (point) p1',
178
+ 'p1%x = 3.4',
179
+ 'p1%y = 4.05',
180
+ 'write(*,*) p1'
181
+ ]
182
+ frepl.run_file(file)
183
+ end
184
+ end
185
+
186
+ context 'with multidimensional targetable array and pointers to said array' do
187
+ it 'works' do
188
+ expect(Frepl).to receive(:output).with(" 1.00000000 2.00000000 3.00000000 4.00000000 \n")
189
+ expect(Frepl).to receive(:output).with(" 1.00000000 \n 3.00000000 \n 2.00000000 \n 4.00000000 \n")
190
+ file = [
191
+ 'integer i, j',
192
+ 'integer, parameter :: m = 2, n = 2',
193
+ 'real, dimension(m,n), target :: A',
194
+ 'real, dimension(:), pointer:: row, column',
195
+ 'a = reshape(([1,2,3,4]), ([2,2]))',
196
+ 'do i = 1, 2',
197
+ 'do j = 1, 2',
198
+ 'write(*,*) a(i,j)',
199
+ 'end do',
200
+ 'end do'
201
+ ]
202
+ frepl.run_file(file)
203
+ end
204
+ end
205
+
206
+ context 'with deeply nested if statements' do
207
+ it 'works' do
208
+ expect(Frepl).to receive(:output).with(" 4\n")
209
+ file = [
210
+ 'if (1 < 2) then',
211
+ 'if (2 < 3) then',
212
+ 'if (3 < 4) then',
213
+ 'write(*,*) 4',
214
+ 'endif',
215
+ 'endif',
216
+ 'endif'
217
+ ]
218
+ frepl.run_file(file)
219
+ end
220
+ end
221
+
222
+ context 'resetting the last statement' do
223
+ it 'works' do
224
+ expect(Frepl).to receive(:output)
225
+ expect(Frepl).to receive(:output).with(" 2\n")
226
+ file = [
227
+ 'integer a',
228
+ 'b = 2',
229
+ 'f:z',
230
+ 'integer :: b = 2',
231
+ 'b'
232
+ ]
233
+ frepl.run_file(file)
234
+ end
235
+ end
236
+
237
+ context 'where statement' do
238
+ it 'works' do
239
+ expect(Frepl).to receive(:output).with(" 1 2 3 4 5 6 7 8 9 10\n")
240
+ expect(Frepl).to receive(:output).with(" 0 0 0 0 0 1 1 1 1 1\n")
241
+ file = [
242
+ 'integer, dimension(10) :: a, b',
243
+ 'integer i',
244
+ 'a = ([ (i, i=1,10) ])',
245
+ 'where (a > 5)',
246
+ 'b = 1.',
247
+ 'elsewhere',
248
+ 'b = 0.',
249
+ 'end where',
250
+ 'b'
251
+ ]
252
+ frepl.run_file(file)
253
+ end
254
+ end
255
+ end
256
+ end