frepl 0.0.1

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.
@@ -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