BOAST 0.9994 → 0.9995
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.
- data/BOAST.gemspec +4 -1
- data/lib/BOAST/Algorithm.rb +59 -52
- data/lib/BOAST/BOAST_OpenCL.rb +8 -8
- data/lib/BOAST/CKernel.rb +11 -15
- data/lib/BOAST/Case.rb +63 -69
- data/lib/BOAST/ControlStructure.rb +13 -0
- data/lib/BOAST/DataTypes.rb +35 -41
- data/lib/BOAST/Expression.rb +16 -20
- data/lib/BOAST/For.rb +44 -45
- data/lib/BOAST/FuncCall.rb +14 -16
- data/lib/BOAST/Functors.rb +19 -0
- data/lib/BOAST/If.rb +63 -62
- data/lib/BOAST/Index.rb +18 -15
- data/lib/BOAST/Inspectable.rb +28 -0
- data/lib/BOAST/Operators.rb +15 -12
- data/lib/BOAST/Parens.rb +2 -2
- data/lib/BOAST/Pragma.rb +6 -11
- data/lib/BOAST/Procedure.rb +70 -52
- data/lib/BOAST/Variable.rb +58 -81
- data/lib/BOAST/While.rb +44 -44
- data/lib/BOAST.rb +4 -1
- metadata +5 -2
data/BOAST.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'BOAST'
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.9995"
|
4
4
|
s.author = "Brice Videau"
|
5
5
|
s.email = "brice.videau@imag.fr"
|
6
6
|
s.homepage = "https://forge.imag.fr/projects/boast/"
|
@@ -27,6 +27,9 @@ Gem::Specification.new do |s|
|
|
27
27
|
lib/BOAST/While.rb
|
28
28
|
lib/BOAST/FuncCall.rb
|
29
29
|
lib/BOAST/Pragma.rb
|
30
|
+
lib/BOAST/Inspectable.rb
|
31
|
+
lib/BOAST/Functors.rb
|
32
|
+
lib/BOAST/ControlStructure.rb
|
30
33
|
)
|
31
34
|
s.has_rdoc = true
|
32
35
|
s.license = 'BSD'
|
data/lib/BOAST/Algorithm.rb
CHANGED
@@ -5,18 +5,17 @@ module BOAST
|
|
5
5
|
FORTRAN = 1
|
6
6
|
C = 2
|
7
7
|
CL = 3
|
8
|
-
# OpenCL = 3
|
9
8
|
CUDA = 4
|
10
9
|
X86 = 1
|
11
10
|
ARM = 2
|
12
11
|
|
13
|
-
def
|
12
|
+
def self.get_default_lang
|
14
13
|
lang = BOAST::const_get(ENV["BOAST_LANG"]) if ENV["BOAST_LANG"]
|
15
14
|
return lang if lang
|
16
15
|
return BOAST::FORTRAN
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
18
|
+
def self.get_default_debug
|
20
19
|
debug = false
|
21
20
|
debug = ENV["DEBUG"] if ENV["DEBUG"]
|
22
21
|
return debug
|
@@ -35,9 +34,9 @@ module BOAST
|
|
35
34
|
@@architecture = X86
|
36
35
|
@@debug = BOAST::get_default_debug
|
37
36
|
|
38
|
-
@@env = Hash
|
37
|
+
@@env = Hash::new{|h, k| h[k] = []}
|
39
38
|
|
40
|
-
def
|
39
|
+
def self.push_env(vars = {})
|
41
40
|
vars.each { |key,value|
|
42
41
|
var = nil
|
43
42
|
begin
|
@@ -50,7 +49,7 @@ module BOAST
|
|
50
49
|
}
|
51
50
|
end
|
52
51
|
|
53
|
-
def
|
52
|
+
def self.pop_env(*vars)
|
54
53
|
vars.each { |key|
|
55
54
|
raise "Unknown module variable #{key}!" unless @@env.has_key?(key)
|
56
55
|
ret = @@env[key].pop
|
@@ -59,189 +58,197 @@ module BOAST
|
|
59
58
|
}
|
60
59
|
end
|
61
60
|
|
62
|
-
def
|
61
|
+
def self.print(a)
|
63
62
|
a.print
|
64
63
|
end
|
65
64
|
|
66
|
-
def
|
65
|
+
def self.decl(*a)
|
67
66
|
a.each { |d|
|
68
67
|
d.decl
|
69
68
|
}
|
70
69
|
end
|
71
70
|
|
72
|
-
def
|
71
|
+
def self.close(a)
|
73
72
|
a.close
|
74
73
|
end
|
75
74
|
|
76
|
-
def
|
75
|
+
def self.open(a)
|
76
|
+
a.open
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.debug=(debug)
|
77
80
|
@@debug = debug
|
78
81
|
end
|
79
82
|
|
80
|
-
def
|
83
|
+
def self.debug
|
81
84
|
return @@debug
|
82
85
|
end
|
83
86
|
|
84
|
-
def
|
87
|
+
def self.architecture=(arch)
|
85
88
|
@@architecture = arch
|
86
89
|
end
|
87
90
|
|
88
|
-
def
|
91
|
+
def self.set_architecture(arch)
|
89
92
|
@@architecture = arch
|
90
93
|
end
|
91
94
|
|
92
|
-
def
|
95
|
+
def self.architecture
|
93
96
|
return @@architecture
|
94
97
|
end
|
95
98
|
|
96
|
-
def
|
99
|
+
def self.get_architecture
|
97
100
|
return @@architecture
|
98
101
|
end
|
99
102
|
|
100
|
-
def
|
103
|
+
def self.indent_level=(level)
|
101
104
|
@@indent_level = level
|
102
105
|
end
|
103
106
|
|
104
|
-
def
|
107
|
+
def self.set_indent_level(level)
|
105
108
|
@@indent_level = level
|
106
109
|
end
|
107
110
|
|
108
|
-
def
|
111
|
+
def self.indent_level
|
109
112
|
return @@indent_level
|
110
113
|
end
|
111
114
|
|
112
|
-
def
|
115
|
+
def self.get_indent_level
|
113
116
|
return @@indent_level
|
114
117
|
end
|
115
118
|
|
116
|
-
def
|
119
|
+
def self.indent_increment
|
117
120
|
return @@indent_increment
|
118
121
|
end
|
119
122
|
|
120
|
-
def
|
123
|
+
def self.get_indent_increment
|
121
124
|
return @@indent_increment
|
122
125
|
end
|
123
126
|
|
124
|
-
def
|
127
|
+
def self.increment_indent_level(increment = @@indent_increment)
|
125
128
|
@@indent_level += increment
|
126
129
|
end
|
127
130
|
|
128
|
-
def
|
131
|
+
def self.decrement_indent_level(increment = @@indent_increment)
|
129
132
|
@@indent_level -= increment
|
130
133
|
end
|
134
|
+
|
135
|
+
def self.indent
|
136
|
+
return " "*BOAST::get_indent_level
|
137
|
+
end
|
131
138
|
|
132
|
-
def
|
139
|
+
def self.set_replace_constants(replace_constants)
|
133
140
|
@@replace_constants = replace_constants
|
134
141
|
end
|
135
142
|
|
136
|
-
def
|
143
|
+
def self.replace_constants?
|
137
144
|
return @@replace_constants
|
138
145
|
end
|
139
146
|
|
140
|
-
def
|
147
|
+
def self.get_replace_constants
|
141
148
|
return @@replace_constants
|
142
149
|
end
|
143
150
|
|
144
|
-
def
|
151
|
+
def self.default_int_signed=(signed)
|
145
152
|
@@default_int_signed = signed
|
146
153
|
end
|
147
154
|
|
148
|
-
def
|
155
|
+
def self.set_default_int_signed(signed)
|
149
156
|
@@default_int_signed = signed
|
150
157
|
end
|
151
158
|
|
152
|
-
def
|
159
|
+
def self.default_int_signed?
|
153
160
|
return @@default_int_signed
|
154
161
|
end
|
155
162
|
|
156
|
-
def
|
163
|
+
def self.get_default_int_signed
|
157
164
|
return @@default_int_signed
|
158
165
|
end
|
159
166
|
|
160
|
-
def
|
167
|
+
def self.default_int_size=(size)
|
161
168
|
@@default_int_size = size
|
162
169
|
end
|
163
170
|
|
164
|
-
def
|
171
|
+
def self.set_default_int_size(size)
|
165
172
|
@@default_int_size = size
|
166
173
|
end
|
167
174
|
|
168
|
-
def
|
175
|
+
def self.default_int_size
|
169
176
|
return @@default_int_size
|
170
177
|
end
|
171
178
|
|
172
|
-
def
|
179
|
+
def self.get_default_int_size
|
173
180
|
return @@default_int_size
|
174
181
|
end
|
175
182
|
|
176
|
-
def
|
183
|
+
def self.default_real_size=(size)
|
177
184
|
@@default_real_size = size
|
178
185
|
end
|
179
186
|
|
180
|
-
def
|
187
|
+
def self.set_default_real_size(size)
|
181
188
|
@@default_real_size = size
|
182
189
|
end
|
183
190
|
|
184
|
-
def
|
191
|
+
def self.default_real_size
|
185
192
|
return @@default_real_size
|
186
193
|
end
|
187
194
|
|
188
|
-
def
|
195
|
+
def self.get_default_real_size
|
189
196
|
return @@default_real_size
|
190
197
|
end
|
191
198
|
|
192
|
-
def
|
199
|
+
def self.lang=(lang)
|
193
200
|
@@lang = lang
|
194
201
|
end
|
195
202
|
|
196
|
-
def
|
203
|
+
def self.set_lang(lang)
|
197
204
|
@@lang = lang
|
198
205
|
end
|
199
206
|
|
200
|
-
def
|
207
|
+
def self.lang
|
201
208
|
return @@lang
|
202
209
|
end
|
203
210
|
|
204
|
-
def
|
211
|
+
def self.get_lang
|
205
212
|
return @@lang
|
206
213
|
end
|
207
214
|
|
208
|
-
def
|
215
|
+
def self.output(output)
|
209
216
|
@@output = output
|
210
217
|
end
|
211
218
|
|
212
|
-
def
|
219
|
+
def self.set_output(output)
|
213
220
|
@@output = output
|
214
221
|
end
|
215
222
|
|
216
|
-
def
|
223
|
+
def self.output
|
217
224
|
return @@output
|
218
225
|
end
|
219
226
|
|
220
|
-
def
|
227
|
+
def self.get_output
|
221
228
|
return @@output
|
222
229
|
end
|
223
230
|
|
224
|
-
def
|
231
|
+
def self.set_chain_code(chain_code)
|
225
232
|
@@chain_code = chain_code
|
226
233
|
end
|
227
234
|
|
228
|
-
def
|
235
|
+
def self.get_chain_code
|
229
236
|
return @@chain_code
|
230
237
|
end
|
231
238
|
|
232
|
-
def
|
239
|
+
def self.array_start=(array_start)
|
233
240
|
@@array_start = array_start
|
234
241
|
end
|
235
242
|
|
236
|
-
def
|
243
|
+
def self.set_array_start(array_start)
|
237
244
|
@@array_start = array_start
|
238
245
|
end
|
239
246
|
|
240
|
-
def
|
247
|
+
def self.array_start
|
241
248
|
return @@array_start
|
242
249
|
end
|
243
250
|
|
244
|
-
def
|
251
|
+
def self.get_array_start
|
245
252
|
return @@array_start
|
246
253
|
end
|
247
254
|
|
data/lib/BOAST/BOAST_OpenCL.rb
CHANGED
@@ -6,7 +6,7 @@ module BOAST
|
|
6
6
|
@@cuda_blockDim = CStruct("blockDim",:type_name => "cuda_blockDim", :members => [Int("x", :signed => false),Int("y", :signed => false),Int("z", :signed => false)])
|
7
7
|
@@cuda_gridDim = CStruct("gridDim",:type_name => "cuda_gridDim", :members => [Int("x", :signed => false),Int("y", :signed => false),Int("z", :signed => false)])
|
8
8
|
|
9
|
-
def
|
9
|
+
def self.barrier(*locality)
|
10
10
|
if @@lang == CL then
|
11
11
|
loc=""
|
12
12
|
if locality.include?(:local) and locality.include?(:global) then
|
@@ -26,7 +26,7 @@ module BOAST
|
|
26
26
|
end
|
27
27
|
|
28
28
|
|
29
|
-
def
|
29
|
+
def self.get_work_dim
|
30
30
|
if @@lang == CL then
|
31
31
|
return FuncCall::new("get_work_dim", :returns => Int("wd", :signed => false))
|
32
32
|
else
|
@@ -34,7 +34,7 @@ module BOAST
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def self.get_global_size(dim)
|
38
38
|
if @@lang == CL then
|
39
39
|
return FuncCall::new("get_global_size", dim, :returns => Sizet)
|
40
40
|
elsif @@lang == CUDA then
|
@@ -46,7 +46,7 @@ module BOAST
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
49
|
+
def self.get_global_id(dim)
|
50
50
|
if @@lang == CL then
|
51
51
|
return FuncCall::new("get_global_id",dim, :returns => Sizet)
|
52
52
|
elsif @@lang == CUDA then
|
@@ -58,7 +58,7 @@ module BOAST
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
61
|
+
def self.get_local_size(dim)
|
62
62
|
if @@lang == CL then
|
63
63
|
return FuncCall::new("get_local_size",dim, :returns => Sizet)
|
64
64
|
elsif @@lang == CUDA then
|
@@ -70,7 +70,7 @@ module BOAST
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
73
|
+
def self.get_local_id(dim)
|
74
74
|
if @@lang == CL then
|
75
75
|
return FuncCall::new("get_local_id",dim, :returns => Sizet)
|
76
76
|
elsif @@lang == CUDA then
|
@@ -82,7 +82,7 @@ module BOAST
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
def
|
85
|
+
def self.get_num_groups(dim)
|
86
86
|
if @@lang == CL then
|
87
87
|
return FuncCall::new("get_num_groups",dim, :returns => Sizet)
|
88
88
|
elsif @@lang == CUDA then
|
@@ -94,7 +94,7 @@ module BOAST
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def self.get_group_id(dim)
|
98
98
|
if @@lang == CL then
|
99
99
|
return FuncCall::new("get_group_id",dim, :returns => Sizet)
|
100
100
|
elsif @@lang == CUDA then
|
data/lib/BOAST/CKernel.rb
CHANGED
@@ -36,7 +36,7 @@ module BOAST
|
|
36
36
|
"icpc" => "-openmp"
|
37
37
|
}
|
38
38
|
|
39
|
-
def
|
39
|
+
def self.read_boast_config
|
40
40
|
home_config_dir = ENV["XDG_CONFIG_HOME"]
|
41
41
|
home_config_dir = "#{Dir.home}/.config" if not home_config_dir
|
42
42
|
Dir.mkdir( home_config_dir ) if not File::exist?( home_config_dir )
|
@@ -72,33 +72,34 @@ module BOAST
|
|
72
72
|
|
73
73
|
BOAST::read_boast_config
|
74
74
|
|
75
|
-
def
|
75
|
+
def self.get_openmp_flags
|
76
76
|
return @@openmp_default_flags.clone
|
77
77
|
end
|
78
78
|
|
79
|
-
def
|
79
|
+
def self.get_compiler_options
|
80
80
|
return @@compiler_default_options.clone
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
83
|
+
def self.verbose
|
84
84
|
return @@verbose
|
85
85
|
end
|
86
86
|
|
87
87
|
|
88
|
-
def
|
88
|
+
def self.get_verbose
|
89
89
|
return @@verbose
|
90
90
|
end
|
91
91
|
|
92
|
-
def
|
92
|
+
def self.verbose=(verbose)
|
93
93
|
@@verbose = verbose
|
94
94
|
end
|
95
95
|
|
96
|
-
def
|
96
|
+
def self.set_verbose(verbose)
|
97
97
|
@@verbose = verbose
|
98
98
|
end
|
99
99
|
|
100
100
|
class CKernel
|
101
101
|
include Rake::DSL
|
102
|
+
include BOAST::Inspectable
|
102
103
|
attr_accessor :code
|
103
104
|
attr_accessor :procedure
|
104
105
|
attr_accessor :lang
|
@@ -133,11 +134,6 @@ module BOAST
|
|
133
134
|
puts @code.read
|
134
135
|
end
|
135
136
|
|
136
|
-
def to_str
|
137
|
-
@code.rewind
|
138
|
-
return code.read
|
139
|
-
end
|
140
|
-
|
141
137
|
def to_s
|
142
138
|
@code.rewind
|
143
139
|
return code.read
|
@@ -431,7 +427,7 @@ EOF
|
|
431
427
|
BOAST::set_output(module_file)
|
432
428
|
fill_module(module_file, module_name)
|
433
429
|
module_file.rewind
|
434
|
-
#
|
430
|
+
#puts module_file.read
|
435
431
|
module_file.close
|
436
432
|
BOAST::set_lang(previous_lang)
|
437
433
|
BOAST::set_output(previous_output)
|
@@ -474,7 +470,7 @@ EOF
|
|
474
470
|
if @lang == BOAST::CUDA then
|
475
471
|
source_file.write <<EOF
|
476
472
|
extern "C" {
|
477
|
-
#{@procedure.
|
473
|
+
#{@procedure.boast_header_s(BOAST::CUDA)}{
|
478
474
|
dim3 dimBlock(block_size[0], block_size[1], block_size[2]);
|
479
475
|
dim3 dimGrid(block_number[0], block_number[1], block_number[2]);
|
480
476
|
cudaEvent_t __start, __stop;
|
@@ -506,7 +502,7 @@ EOF
|
|
506
502
|
if( @lang == BOAST::CUDA ) then
|
507
503
|
module_file.print "#include <cuda_runtime.h>\n"
|
508
504
|
end
|
509
|
-
|
505
|
+
@procedure.boast_header(@lang)
|
510
506
|
module_file.write <<EOF
|
511
507
|
VALUE #{module_name} = Qnil;
|
512
508
|
void Init_#{module_name}();
|
data/lib/BOAST/Case.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module BOAST
|
2
2
|
|
3
|
-
class Case
|
4
|
-
|
5
|
-
|
6
|
-
end
|
3
|
+
class Case < BOAST::ControlStructure
|
4
|
+
include BOAST::Inspectable
|
5
|
+
extend BOAST::Functor
|
7
6
|
|
8
7
|
attr_reader :expression
|
9
8
|
attr_reader :constants_list
|
@@ -28,88 +27,83 @@ module BOAST
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
@@c_strings = {
|
31
|
+
:switch => '"switch (#{expr}) {"',
|
32
|
+
:case => '"case #{constants.join(" : case")} :"',
|
33
|
+
:default => '"default :"',
|
34
|
+
:break => '"break;"',
|
35
|
+
:end => '"}"'
|
36
|
+
}
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
@@f_strings = {
|
39
|
+
:switch => '"select case (#{expr})"',
|
40
|
+
:case => '"case (#{constants.join(" : ")})"',
|
41
|
+
:default => '"case default"',
|
42
|
+
:break => 'nil',
|
43
|
+
:end => '"end select"'
|
44
|
+
}
|
45
|
+
|
46
|
+
@@strings = {
|
47
|
+
BOAST::C => @@c_strings,
|
48
|
+
BOAST::CL => @@c_strings,
|
49
|
+
BOAST::CUDA => @@c_strings,
|
50
|
+
BOAST::FORTRAN => @@f_strings
|
51
|
+
}
|
39
52
|
|
40
|
-
|
53
|
+
eval token_string_generator( * %w{switch expr})
|
54
|
+
eval token_string_generator( * %w{case constants})
|
55
|
+
eval token_string_generator( * %w{default})
|
56
|
+
eval token_string_generator( * %w{break})
|
57
|
+
eval token_string_generator( * %w{end})
|
58
|
+
|
59
|
+
def to_s(block_number = nil)
|
41
60
|
s = ""
|
42
|
-
if
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
BOAST::
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
61
|
+
if block_number then
|
62
|
+
if block_number != 0 then
|
63
|
+
s += BOAST::indent + break_string + "\n" if break_string
|
64
|
+
BOAST::decrement_indent_level
|
65
|
+
end
|
66
|
+
s += BOAST::indent
|
67
|
+
if @constants_list[block_number] and @constants_list[block_number].size > 0 then
|
68
|
+
s += case_string(@constants_list[block_number])
|
69
|
+
else
|
70
|
+
s += default_string
|
71
|
+
end
|
52
72
|
else
|
53
|
-
s +=
|
73
|
+
s += BOAST::indent
|
74
|
+
s += switch_string(@expression)
|
54
75
|
end
|
55
76
|
BOAST::increment_indent_level
|
56
77
|
return s
|
57
78
|
end
|
58
79
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
s += " "*BOAST::get_indent_level
|
63
|
-
s += "switch(#{@expression}){\n"
|
64
|
-
BOAST::increment_indent_level
|
65
|
-
else
|
66
|
-
s += " "*BOAST::get_indent_level + "break;\n"
|
67
|
-
BOAST::decrement_indent_level
|
68
|
-
end
|
69
|
-
s += " "*BOAST::get_indent_level
|
70
|
-
if constants and constants.size>0 then
|
71
|
-
s += "case #{constants.join(" : case")} :"
|
72
|
-
else
|
73
|
-
s += "default :"
|
74
|
-
end
|
75
|
-
BOAST::increment_indent_level
|
76
|
-
return s
|
80
|
+
def open
|
81
|
+
BOAST::get_output.puts self.to_s
|
82
|
+
return self
|
77
83
|
end
|
78
84
|
|
79
85
|
def print(*args)
|
80
|
-
|
81
|
-
@blocks.
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
self.open
|
87
|
+
if @blocks.size > 0 then
|
88
|
+
@blocks.each_index { |indx|
|
89
|
+
s = self.to_s(indx)
|
90
|
+
BOAST::get_output.puts s
|
91
|
+
@blocks[indx].call(*args)
|
92
|
+
}
|
93
|
+
self.close
|
94
|
+
end
|
88
95
|
return self
|
89
96
|
end
|
90
|
-
|
91
|
-
|
92
|
-
return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
|
93
|
-
end
|
94
|
-
def close_c(final=true)
|
95
|
-
s = ""
|
96
|
-
s += " "*BOAST::get_indent_level if final
|
97
|
-
s += "break;\n"
|
98
|
-
BOAST::decrement_indent_level
|
99
|
-
s += " "*BOAST::get_indent_level if final
|
100
|
-
s += "}"
|
101
|
-
BOAST::decrement_indent_level
|
102
|
-
BOAST::get_output.puts s if final
|
103
|
-
return s
|
104
|
-
end
|
105
|
-
def close_fortran(final=true)
|
97
|
+
|
98
|
+
def close
|
106
99
|
s = ""
|
100
|
+
s += BOAST::indent + break_string + "\n" if break_string
|
107
101
|
BOAST::decrement_indent_level
|
108
|
-
s +=
|
109
|
-
s +=
|
102
|
+
s += BOAST::indent
|
103
|
+
s += end_string
|
110
104
|
BOAST::decrement_indent_level
|
111
|
-
BOAST::get_output.puts s
|
112
|
-
return
|
105
|
+
BOAST::get_output.puts s
|
106
|
+
return self
|
113
107
|
end
|
114
108
|
|
115
109
|
end
|