at_coder_friends 0.6.2 → 0.6.7
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 +4 -4
- data/.rubocop.yml +3 -2
- data/.travis.yml +2 -2
- data/CHANGELOG.md +53 -0
- data/Gemfile.lock +32 -36
- data/README.md +1 -1
- data/at_coder_friends.gemspec +5 -7
- data/config/default.yml +146 -72
- data/docs/CONFIGURATION.md +224 -140
- data/lib/at_coder_friends.rb +3 -0
- data/lib/at_coder_friends/cli.rb +8 -0
- data/lib/at_coder_friends/config_loader.rb +11 -3
- data/lib/at_coder_friends/context.rb +10 -6
- data/lib/at_coder_friends/emitter.rb +2 -2
- data/lib/at_coder_friends/generator/base.rb +42 -0
- data/lib/at_coder_friends/generator/cxx_builtin.rb +196 -143
- data/lib/at_coder_friends/generator/main.rb +8 -2
- data/lib/at_coder_friends/generator/ruby_builtin.rb +97 -51
- data/lib/at_coder_friends/parser/constraints.rb +1 -0
- data/lib/at_coder_friends/parser/input_format.rb +389 -188
- data/lib/at_coder_friends/parser/input_type.rb +92 -0
- data/lib/at_coder_friends/parser/main.rb +1 -0
- data/lib/at_coder_friends/parser/modulo.rb +1 -1
- data/lib/at_coder_friends/parser/sections.rb +3 -3
- data/lib/at_coder_friends/path_info.rb +51 -0
- data/lib/at_coder_friends/path_util.rb +0 -31
- data/lib/at_coder_friends/problem.rb +81 -6
- data/lib/at_coder_friends/scraping/agent.rb +11 -2
- data/lib/at_coder_friends/scraping/custom_test.rb +5 -6
- data/lib/at_coder_friends/scraping/submission.rb +6 -7
- data/lib/at_coder_friends/scraping/tasks.rb +8 -3
- data/lib/at_coder_friends/test_runner/base.rb +17 -4
- data/lib/at_coder_friends/test_runner/judge.rb +7 -9
- data/lib/at_coder_friends/test_runner/sample.rb +2 -4
- data/lib/at_coder_friends/verifier.rb +2 -3
- data/lib/at_coder_friends/version.rb +1 -1
- data/templates/{cxx_builtin_interactive.cxx → cxx_builtin.cxx.erb} +26 -4
- data/templates/{ruby_builtin_interactive.rb → ruby_builtin.rb.erb} +17 -3
- metadata +11 -17
- data/tasks/regression/check_const.rake +0 -136
- data/tasks/regression/check_diff.rake +0 -30
- data/tasks/regression/check_fmt.rake +0 -42
- data/tasks/regression/check_parse.rake +0 -70
- data/tasks/regression/regression.rb +0 -72
- data/tasks/regression/section_list.rake +0 -53
- data/tasks/regression/setup.rake +0 -48
- data/templates/cxx_builtin_default.cxx +0 -26
- data/templates/ruby_builtin_default.rb +0 -7
@@ -11,20 +11,28 @@ module AtCoderFriends
|
|
11
11
|
DEFAULT_FILE = File.join(ACF_HOME, 'config', 'default.yml')
|
12
12
|
|
13
13
|
class << self
|
14
|
+
def dotfile
|
15
|
+
DOTFILE
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_file
|
19
|
+
DEFAULT_FILE
|
20
|
+
end
|
21
|
+
|
14
22
|
def load_config(ctx)
|
15
23
|
path = config_file_for(ctx.path)
|
16
24
|
config = load_yaml(path)
|
17
|
-
return config if path ==
|
25
|
+
return config if path == default_file
|
18
26
|
|
19
27
|
merge_with_default(config)
|
20
28
|
end
|
21
29
|
|
22
30
|
def config_file_for(target_dir)
|
23
|
-
find_project_dotfile(target_dir) ||
|
31
|
+
find_project_dotfile(target_dir) || default_file
|
24
32
|
end
|
25
33
|
|
26
34
|
def find_project_dotfile(target_dir)
|
27
|
-
find_file_upwards(
|
35
|
+
find_file_upwards(dotfile, target_dir)
|
28
36
|
end
|
29
37
|
|
30
38
|
def find_file_upwards(filename, start_dir)
|
@@ -7,11 +7,15 @@ module AtCoderFriends
|
|
7
7
|
# - configuration
|
8
8
|
# - application modules
|
9
9
|
class Context
|
10
|
-
attr_reader :options, :
|
10
|
+
attr_reader :options, :path_info
|
11
11
|
|
12
12
|
def initialize(options, path)
|
13
13
|
@options = options
|
14
|
-
@
|
14
|
+
@path_info = PathInfo.new(File.expand_path(path))
|
15
|
+
end
|
16
|
+
|
17
|
+
def path
|
18
|
+
path_info.path
|
15
19
|
end
|
16
20
|
|
17
21
|
def config
|
@@ -26,6 +30,10 @@ module AtCoderFriends
|
|
26
30
|
@generator ||= Generator::Main.new(self)
|
27
31
|
end
|
28
32
|
|
33
|
+
def emitter
|
34
|
+
@emitter ||= Emitter.new(self)
|
35
|
+
end
|
36
|
+
|
29
37
|
def sample_test_runner
|
30
38
|
@sample_test_runner ||= TestRunner::Sample.new(self)
|
31
39
|
end
|
@@ -38,10 +46,6 @@ module AtCoderFriends
|
|
38
46
|
@verifier ||= Verifier.new(self)
|
39
47
|
end
|
40
48
|
|
41
|
-
def emitter
|
42
|
-
@emitter ||= Emitter.new(self)
|
43
|
-
end
|
44
|
-
|
45
49
|
def post_process
|
46
50
|
@scraping_agent&.save_session
|
47
51
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module AtCoderFriends
|
6
|
+
module Generator
|
7
|
+
Attributes = Struct.new(:file_ext, :default_template)
|
8
|
+
|
9
|
+
# common behavior of generators
|
10
|
+
class Base
|
11
|
+
attr_reader :cfg, :pbm
|
12
|
+
|
13
|
+
def initialize(cfg = nil)
|
14
|
+
@cfg = cfg || {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def process(pbm)
|
18
|
+
pbm.add_src(attrs.file_ext, generate(pbm))
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate(pbm)
|
22
|
+
@pbm = pbm
|
23
|
+
src = File.read(select_template)
|
24
|
+
src = ERB.new(src, safe_level = nil, trim_mode = '-').result(binding)
|
25
|
+
src = render(src) if respond_to?(:render)
|
26
|
+
src
|
27
|
+
end
|
28
|
+
|
29
|
+
def select_template
|
30
|
+
cfg['default_template'] || attrs.default_template
|
31
|
+
end
|
32
|
+
|
33
|
+
def embed_lines(src, pat, lines)
|
34
|
+
re = Regexp.escape(pat)
|
35
|
+
src.gsub(
|
36
|
+
/^(.*)#{re}(.*)$\n/,
|
37
|
+
lines.compact.map { |s| "\\1#{s}\\2\n" }.join
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -2,96 +2,8 @@
|
|
2
2
|
|
3
3
|
module AtCoderFriends
|
4
4
|
module Generator
|
5
|
-
|
6
|
-
|
7
|
-
TMPL_DIR = File.join(ACF_HOME, 'templates')
|
8
|
-
DEFAULT_TMPL = File.join(TMPL_DIR, 'cxx_builtin_default.cxx')
|
9
|
-
INTERACTIVE_TMPL = File.join(TMPL_DIR, 'cxx_builtin_interactive.cxx')
|
10
|
-
SCANF_FMTS = [
|
11
|
-
'scanf("%<fmt>s", %<addr>s);',
|
12
|
-
'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
|
13
|
-
'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
|
14
|
-
].freeze
|
15
|
-
FMT_FMTS = { number: '%d', string: '%s', char: '%s' }.freeze
|
16
|
-
ADDR_FMTS = {
|
17
|
-
single: {
|
18
|
-
number: '&%<v>s',
|
19
|
-
string: '%<v>s'
|
20
|
-
},
|
21
|
-
harray: {
|
22
|
-
number: '%<v>s + i',
|
23
|
-
string: '%<v>s[i]',
|
24
|
-
char: '%<v>s'
|
25
|
-
},
|
26
|
-
varray: {
|
27
|
-
number: '%<v>s + i',
|
28
|
-
string: '%<v>s[i]'
|
29
|
-
},
|
30
|
-
matrix: {
|
31
|
-
number: '&%<v>s[i][j]',
|
32
|
-
string: '%<v>s[i][j]',
|
33
|
-
char: '%<v>s[i]'
|
34
|
-
}
|
35
|
-
}.freeze
|
36
|
-
DEFAULT_OUTPUT = <<~TEXT
|
37
|
-
int ans = 0;
|
38
|
-
printf("%d\\n", ans);
|
39
|
-
TEXT
|
40
|
-
BINARY_OUTPUT_FMT = <<~TEXT
|
41
|
-
bool cond = false;
|
42
|
-
puts(cond ? "%s" : "%s");
|
43
|
-
TEXT
|
44
|
-
end
|
45
|
-
|
46
|
-
# generates C++ source from problem description
|
47
|
-
class CxxBuiltin
|
48
|
-
include CxxBuiltinConstants
|
49
|
-
|
50
|
-
attr_reader :cfg, :pbm
|
51
|
-
|
52
|
-
def initialize(cfg = nil)
|
53
|
-
@cfg = cfg || {}
|
54
|
-
end
|
55
|
-
|
56
|
-
def process(pbm)
|
57
|
-
src = generate(pbm)
|
58
|
-
pbm.add_src(:cxx, src)
|
59
|
-
end
|
60
|
-
|
61
|
-
def generate(pbm)
|
62
|
-
@pbm = pbm
|
63
|
-
src = File.read(select_template)
|
64
|
-
src = embed_lines(src, '/*** URL ***/', [pbm.url])
|
65
|
-
src = embed_lines(src, '/*** CONSTS ***/', gen_consts)
|
66
|
-
src = embed_lines(src, '/*** DCLS ***/', gen_decls)
|
67
|
-
src = embed_lines(src, '/*** INPUTS ***/', gen_inputs)
|
68
|
-
embed_lines(src, '/*** OUTPUT ***/', gen_output.split("\n"))
|
69
|
-
end
|
70
|
-
|
71
|
-
def embed_lines(src, pat, lines)
|
72
|
-
re = Regexp.escape(pat)
|
73
|
-
src.gsub(
|
74
|
-
/^(.*)#{re}(.*)$/,
|
75
|
-
lines.map { |s| '\1' + s + '\2' }.join("\n")
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
|
-
def select_template(interactive = pbm.options.interactive)
|
80
|
-
interactive ? interactive_template : default_template
|
81
|
-
end
|
82
|
-
|
83
|
-
def default_template
|
84
|
-
cfg['default_template'] || DEFAULT_TMPL
|
85
|
-
end
|
86
|
-
|
87
|
-
def interactive_template
|
88
|
-
cfg['interactive_template'] || INTERACTIVE_TMPL
|
89
|
-
end
|
90
|
-
|
91
|
-
def gen_consts(constants = pbm.constants)
|
92
|
-
constants.map { |c| gen_const(c) }
|
93
|
-
end
|
94
|
-
|
5
|
+
# generates C++ constants
|
6
|
+
module CxxBuiltinConstGen
|
95
7
|
def gen_const(c)
|
96
8
|
v = cnv_const_value(c.value)
|
97
9
|
if c.type == :max
|
@@ -107,98 +19,239 @@ module AtCoderFriends
|
|
107
19
|
.sub(/\b2\^/, '1<<')
|
108
20
|
.gsub(',', "'")
|
109
21
|
end
|
22
|
+
end
|
110
23
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
24
|
+
# generates C++ variable declarations
|
25
|
+
module CxxBuiltinDeclGen
|
26
|
+
TYPE_TBL = {
|
27
|
+
number: 'int',
|
28
|
+
decimal: 'double',
|
29
|
+
string: 'char',
|
30
|
+
char: 'char'
|
31
|
+
}.tap { |h| h.default = 'int' }
|
115
32
|
def gen_decl(inpdef)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
33
|
+
if inpdef.components
|
34
|
+
inpdef.components.map { |cmp| gen_decl(cmp) }
|
35
|
+
else
|
36
|
+
case inpdef.container
|
37
|
+
when :single
|
38
|
+
gen_single_decl(inpdef)
|
39
|
+
when :harray
|
40
|
+
gen_harray_decl(inpdef)
|
41
|
+
when :varray
|
42
|
+
gen_varray_decl(inpdef)
|
43
|
+
when :matrix, :vmatrix, :hmatrix
|
44
|
+
gen_matrix_decl(inpdef)
|
45
|
+
end
|
125
46
|
end
|
126
47
|
end
|
127
48
|
|
128
49
|
def gen_single_decl(inpdef)
|
129
|
-
names = inpdef.
|
130
|
-
|
131
|
-
|
50
|
+
names, cols = inpdef.vars.transpose
|
51
|
+
if cols.uniq.size == 1 && cols[0] != :string
|
52
|
+
type = TYPE_TBL[cols[0]]
|
132
53
|
dcl = names.join(', ')
|
133
|
-
"
|
134
|
-
|
135
|
-
|
54
|
+
"#{type} #{dcl};"
|
55
|
+
else
|
56
|
+
inpdef.vars.map do |v, item|
|
57
|
+
type = TYPE_TBL[item]
|
58
|
+
dcl = v
|
59
|
+
dcl += "[#{v.upcase}_MAX + 1]" if item == :string
|
60
|
+
"#{type} #{dcl};"
|
61
|
+
end
|
136
62
|
end
|
137
63
|
end
|
138
64
|
|
139
65
|
def gen_harray_decl(inpdef)
|
66
|
+
type = TYPE_TBL[inpdef.item]
|
140
67
|
v = inpdef.names[0]
|
141
68
|
sz = gen_arr_size(inpdef.size)[0]
|
142
69
|
case inpdef.item
|
143
|
-
when :number
|
144
|
-
"
|
70
|
+
when :number, :decimal
|
71
|
+
"#{type} #{v}[#{sz}];"
|
145
72
|
when :string
|
146
|
-
"
|
73
|
+
"#{type} #{v}[#{sz}][#{v.upcase}_MAX + 1];"
|
147
74
|
when :char
|
148
|
-
"
|
75
|
+
"#{type} #{v}[#{sz} + 1];"
|
149
76
|
end
|
150
77
|
end
|
151
78
|
|
152
79
|
def gen_varray_decl(inpdef)
|
153
|
-
names = inpdef.names
|
154
80
|
sz = gen_arr_size(inpdef.size)[0]
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
81
|
+
inpdef.vars.map do |v, item|
|
82
|
+
type = TYPE_TBL[item]
|
83
|
+
dcl = "#{v}[#{sz}]"
|
84
|
+
dcl += "[#{v.upcase}_MAX + 1]" if item == :string
|
85
|
+
"#{type} #{dcl};"
|
160
86
|
end
|
161
87
|
end
|
162
88
|
|
163
89
|
def gen_matrix_decl(inpdef)
|
164
|
-
v = inpdef.names[0]
|
165
90
|
sz1, sz2 = gen_arr_size(inpdef.size)
|
166
|
-
|
167
|
-
|
168
|
-
"
|
169
|
-
|
170
|
-
"
|
171
|
-
|
172
|
-
"char #{v}[#{sz1}][#{sz2} + 1];"
|
91
|
+
inpdef.vars.map do |v, item|
|
92
|
+
type = TYPE_TBL[item]
|
93
|
+
dcl = "#{v}[#{sz1}]"
|
94
|
+
dcl += item == :char ? "[#{sz2} + 1]" : "[#{sz2}]"
|
95
|
+
dcl += "[#{v.upcase}_MAX + 1]" if item == :string
|
96
|
+
"#{type} #{dcl};"
|
173
97
|
end
|
174
98
|
end
|
175
99
|
|
176
100
|
def gen_arr_size(szs)
|
177
101
|
szs.map { |sz| sz.gsub(/([a-z][a-z0-9_]*)/i, '\1_MAX').upcase }
|
178
102
|
end
|
103
|
+
end
|
179
104
|
|
180
|
-
|
181
|
-
|
182
|
-
|
105
|
+
# generates C++ input source
|
106
|
+
module CxxBuiltinInputGen
|
107
|
+
SCANF_FMTS = [
|
108
|
+
'scanf("%<fmt>s", %<addr>s);',
|
109
|
+
'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
|
110
|
+
'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
|
111
|
+
].freeze
|
112
|
+
SCANF_FMTS_CMB = {
|
113
|
+
varray_matrix:
|
114
|
+
[
|
115
|
+
<<~TEXT,
|
116
|
+
REP(i, %<sz1>s) {
|
117
|
+
scanf("%<fmt1>s", %<addr1>s);
|
118
|
+
scanf("%<fmt2>s", %<addr2>s);
|
119
|
+
}
|
120
|
+
TEXT
|
121
|
+
<<~TEXT
|
122
|
+
REP(i, %<sz1>s) {
|
123
|
+
scanf("%<fmt1>s", %<addr1>s);
|
124
|
+
REP(j, %<sz2>s[i]) scanf("%<fmt2>s", %<addr2>s);
|
125
|
+
}
|
126
|
+
TEXT
|
127
|
+
],
|
128
|
+
matrix_varray:
|
129
|
+
[
|
130
|
+
<<~TEXT,
|
131
|
+
REP(i, %<sz1>s) {
|
132
|
+
scanf("%<fmt1>s", %<addr1>s);
|
133
|
+
scanf("%<fmt2>s", %<addr2>s);
|
134
|
+
}
|
135
|
+
TEXT
|
136
|
+
<<~TEXT
|
137
|
+
REP(i, %<sz1>s) {
|
138
|
+
REP(j, %<sz2>s) scanf("%<fmt1>s", %<addr1>s);
|
139
|
+
scanf("%<fmt2>s", %<addr2>s);
|
140
|
+
}
|
141
|
+
TEXT
|
142
|
+
]
|
143
|
+
}.tap { |h| h.default = h[:varray_matrix] }
|
144
|
+
FMT_FMTS = {
|
145
|
+
number: '%d',
|
146
|
+
decimal: '%lf',
|
147
|
+
string: '%s',
|
148
|
+
char: '%s'
|
149
|
+
}.tap { |h| h.default = h[:number] }
|
150
|
+
SINGLE_ADDR_FMTS = {
|
151
|
+
number: '&%<v>s',
|
152
|
+
decimal: '&%<v>s',
|
153
|
+
string: '%<v>s'
|
154
|
+
}.tap { |h| h.default = h[:number] }
|
155
|
+
ARRAY_ADDR_FMTS = {
|
156
|
+
number: '%<v>s + i',
|
157
|
+
decimal: '%<v>s + i',
|
158
|
+
string: '%<v>s[i]',
|
159
|
+
char: '%<v>s'
|
160
|
+
}.tap { |h| h.default = h[:number] }
|
161
|
+
MATRIX_ADDR_FMTS = {
|
162
|
+
number: '&%<v>s[i][j]',
|
163
|
+
decimal: '&%<v>s[i][j]',
|
164
|
+
string: '%<v>s[i][j]',
|
165
|
+
char: '%<v>s[i]'
|
166
|
+
}.tap { |h| h.default = h[:number] }
|
167
|
+
ADDR_FMTS = {
|
168
|
+
single: SINGLE_ADDR_FMTS,
|
169
|
+
harray: ARRAY_ADDR_FMTS,
|
170
|
+
varray: ARRAY_ADDR_FMTS,
|
171
|
+
matrix: MATRIX_ADDR_FMTS,
|
172
|
+
vmatrix: MATRIX_ADDR_FMTS,
|
173
|
+
hmatrix: MATRIX_ADDR_FMTS
|
174
|
+
}.tap { |h| h.default = h[:single] }
|
183
175
|
|
184
|
-
# rubocop:disable Metrics/AbcSize
|
185
176
|
def gen_input(inpdef)
|
186
|
-
|
187
|
-
|
177
|
+
if inpdef.components
|
178
|
+
gen_cmb_input(inpdef)
|
179
|
+
else
|
180
|
+
gen_plain_input(inpdef)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def gen_plain_input(inpdef)
|
185
|
+
scanf = SCANF_FMTS[inpdef.size.size - (inpdef.item == :char ? 1 : 0)]
|
188
186
|
sz1, sz2 = inpdef.size
|
189
|
-
fmt =
|
190
|
-
addr_fmt = ADDR_FMTS[inpdef.container][inpdef.item]
|
191
|
-
addr = inpdef.names.map { |v| format(addr_fmt, v: v) }.join(', ')
|
187
|
+
fmt, addr = scanf_params(inpdef)
|
192
188
|
format(scanf, sz1: sz1, sz2: sz2, fmt: fmt, addr: addr)
|
193
189
|
end
|
194
|
-
# rubocop:enable Metrics/AbcSize
|
195
190
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
191
|
+
def gen_cmb_input(inpdef)
|
192
|
+
scanf = SCANF_FMTS_CMB.dig(
|
193
|
+
inpdef.container, inpdef.item == :char ? 0 : 1
|
194
|
+
)
|
195
|
+
sz1 = inpdef.size[0]
|
196
|
+
sz2 = inpdef.size[1].split('_')[0]
|
197
|
+
fmt1, addr1, fmt2, addr2 =
|
198
|
+
inpdef.components.map { |cmp| scanf_params(cmp) }.flatten
|
199
|
+
format(
|
200
|
+
scanf,
|
201
|
+
sz1: sz1, sz2: sz2,
|
202
|
+
fmt1: fmt1, addr1: addr1,
|
203
|
+
fmt2: fmt2, addr2: addr2
|
204
|
+
).split("\n")
|
205
|
+
end
|
206
|
+
|
207
|
+
def scanf_params(inpdef)
|
208
|
+
[scanf_fmt(inpdef), scanf_addr(inpdef)]
|
209
|
+
end
|
210
|
+
|
211
|
+
def scanf_fmt(inpdef)
|
212
|
+
inpdef.vars.map { |(_v, item)| FMT_FMTS[item] }.join
|
213
|
+
end
|
214
|
+
|
215
|
+
def scanf_addr(inpdef)
|
216
|
+
inpdef.vars.map do |(v, item)|
|
217
|
+
addr_fmt = ADDR_FMTS.dig(inpdef.container, item)
|
218
|
+
format(addr_fmt, v: v)
|
219
|
+
end.join(', ')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# generates C++ source from problem description
|
224
|
+
class CxxBuiltin < Base
|
225
|
+
include CxxBuiltinConstGen
|
226
|
+
include CxxBuiltinDeclGen
|
227
|
+
include CxxBuiltinInputGen
|
228
|
+
|
229
|
+
ACF_HOME = File.realpath(File.join(__dir__, '..', '..', '..'))
|
230
|
+
TMPL_DIR = File.join(ACF_HOME, 'templates')
|
231
|
+
DEFAULT_TMPL = File.join(TMPL_DIR, 'cxx_builtin.cxx.erb')
|
232
|
+
ATTRS = Attributes.new(:cxx, DEFAULT_TMPL)
|
233
|
+
|
234
|
+
def attrs
|
235
|
+
ATTRS
|
236
|
+
end
|
237
|
+
|
238
|
+
def render(src)
|
239
|
+
src = embed_lines(src, '/*** CONSTS ***/', gen_consts)
|
240
|
+
src = embed_lines(src, '/*** DCLS ***/', gen_decls)
|
241
|
+
src = embed_lines(src, '/*** INPUTS ***/', gen_inputs)
|
242
|
+
src
|
243
|
+
end
|
244
|
+
|
245
|
+
def gen_consts(constants = pbm.constants)
|
246
|
+
constants.map { |c| gen_const(c) }
|
247
|
+
end
|
248
|
+
|
249
|
+
def gen_decls(inpdefs = pbm.formats)
|
250
|
+
inpdefs.map { |inpdef| gen_decl(inpdef) }.flatten
|
251
|
+
end
|
252
|
+
|
253
|
+
def gen_inputs(inpdefs = pbm.formats)
|
254
|
+
inpdefs.map { |inpdef| gen_input(inpdef) }.flatten
|
202
255
|
end
|
203
256
|
end
|
204
257
|
end
|