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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +120 -0
- data/Rakefile +15 -0
- data/bin/frepl +5 -0
- data/frepl.gemspec +29 -0
- data/lib/frepl.rb +81 -0
- data/lib/frepl/classifier.rb +190 -0
- data/lib/frepl/fortran_file.rb +159 -0
- data/lib/frepl/statement.rb +93 -0
- data/lib/frepl/statements/allocation.rb +9 -0
- data/lib/frepl/statements/assignment.rb +19 -0
- data/lib/frepl/statements/declaration.rb +47 -0
- data/lib/frepl/statements/derived_type.rb +29 -0
- data/lib/frepl/statements/do_loop.rb +17 -0
- data/lib/frepl/statements/execution.rb +7 -0
- data/lib/frepl/statements/function.rb +29 -0
- data/lib/frepl/statements/if_statement.rb +17 -0
- data/lib/frepl/statements/multi_declaration.rb +70 -0
- data/lib/frepl/statements/repl_command.rb +46 -0
- data/lib/frepl/statements/standalone_variable.rb +15 -0
- data/lib/frepl/statements/subroutine.rb +29 -0
- data/lib/frepl/statements/where.rb +17 -0
- data/lib/frepl/version.rb +3 -0
- data/spec/lib/frepl/assignment_spec.rb +53 -0
- data/spec/lib/frepl/classifier_spec.rb +171 -0
- data/spec/lib/frepl/declaration_spec.rb +193 -0
- data/spec/lib/frepl/function_spec.rb +43 -0
- data/spec/lib/frepl/multi_declaration_spec.rb +123 -0
- data/spec/lib/frepl/subroutine_spec.rb +46 -0
- data/spec/lib/frepl_spec.rb +256 -0
- data/spec/spec_helper.rb +106 -0
- metadata +186 -0
@@ -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
|