Skip to content

Commit ee0d3df

Browse files
authored
Merge pull request #49 from manta1130/code-expander
Implement code expander
2 parents c2bb69c + 4b7e468 commit ee0d3df

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,37 @@ jobs:
9595
args: --workspace --no-fail-fast
9696
env:
9797
RUST_BACKTRACE: full
98+
99+
expander_test:
100+
strategy:
101+
fail-fast: false
102+
matrix:
103+
toolchain:
104+
- 1.42.0-x86_64-unknown-linux-gnu
105+
- stable-x86_64-unknown-linux-gnu
106+
python-version:
107+
- '3.6' # https://packages.ubuntu.com/bionic/python3
108+
- '3.8' # https://packages.ubuntu.com/focal/python3
109+
110+
name: Expand_test (${{ matrix.toolchain }}, ${{ matrix.python-version }})
111+
runs-on: ubuntu-18.04
112+
113+
steps:
114+
- name: Checkout
115+
uses: actions/checkout@v2
116+
117+
- name: 'Setup `${{ matrix.toolchain }}`'
118+
uses: actions-rs/toolchain@v1
119+
with:
120+
toolchain: ${{ matrix.toolchain }}
121+
override: true
122+
profile: minimal
123+
components: rustfmt
124+
125+
- name: Setup Python ${{ matrix.python-version }}
126+
uses: actions/setup-python@v2
127+
with:
128+
python-version: ${{ matrix.python-version }}
129+
130+
- name: expand.py tests
131+
run: bash ./.github/workflows/test-expand.sh

.github/workflows/test-expand.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
TEST_MODULES=(convolution dsu fenwicktree lazysegtree math maxflow mincostflow modint scc segtree string twosat --all)
4+
TMP_PATH=$(mktemp -d)
5+
# shellcheck disable=SC2164
6+
SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
7+
TEST_FILE="test.rs"
8+
FILE_HEAD="fn main() {}"
9+
10+
for MODULE in "${TEST_MODULES[@]}" ;do
11+
echo Test module "$MODULE"
12+
python3 "$SCRIPT_DIR/../../expand.py" "$MODULE" > "$TMP_PATH/$TEST_FILE"
13+
echo Output "$(wc -c < "$TMP_PATH/$TEST_FILE")" Bytes
14+
echo "$FILE_HEAD" >> "$TMP_PATH/$TEST_FILE"
15+
if ! rustc -A warnings "$TMP_PATH/$TEST_FILE";
16+
then
17+
echo Error compiling for "$MODULE"
18+
exit 1
19+
else
20+
echo Test passed
21+
fi
22+
done

expand.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/python3
2+
3+
import sys
4+
import getopt
5+
import tempfile
6+
import subprocess
7+
8+
usage = '''Usage:expand.py [options] <output modules>
9+
Output Modules:
10+
convolution
11+
dsu
12+
fenwicktree
13+
lazysegtree
14+
math
15+
maxflow
16+
mincostflow
17+
modint
18+
scc
19+
segtree
20+
string
21+
twosat
22+
23+
You can select multiple modules for <output modules>
24+
e.g.)expand.py math segtree
25+
26+
Options:
27+
-a --all import all modules
28+
-h --help print help
29+
'''
30+
output_header = '//https://github.com/rust-lang-ja/ac-library-rs\n'
31+
opt_list = ['help', 'all']
32+
output_list_all = ('convolution', 'dsu', 'fenwicktree', 'lazysegtree', 'math',
33+
'maxflow', 'mincostflow', 'modint', 'scc', 'segtree',
34+
'string', 'twosat',
35+
'internal_bit', 'internal_math', 'internal_queue',
36+
'internal_scc', 'internal_type_traits',)
37+
dependency_list = {'convolution': ('internal_bit', 'modint',),
38+
'lazysegtree': ('internal_bit', 'segtree'),
39+
'math': ('internal_math',),
40+
'maxflow': ('internal_type_traits', 'internal_queue',),
41+
'mincostflow': ('internal_type_traits',),
42+
'modint': ('internal_math',),
43+
'scc': ('internal_scc',),
44+
'segtree': ('internal_bit', 'internal_type_traits',),
45+
'twosat': ('internal_scc',), }
46+
src_path = 'src/'
47+
48+
49+
def output_file(filename):
50+
global src_path
51+
52+
res = []
53+
with open(src_path+filename+'.rs', 'r') as f:
54+
res.append('pub mod {} {{'.format(filename))
55+
56+
for line in f:
57+
res.append(line.rstrip())
58+
59+
res.append('}')
60+
return res
61+
62+
63+
try:
64+
opts, args = getopt.getopt(sys.argv[1:], 'ah', opt_list)
65+
except getopt.GetoptError as e:
66+
print(e)
67+
print(usage)
68+
sys.exit(2)
69+
70+
if len(opts) == 0 and len(args) == 0:
71+
print(usage)
72+
sys.exit(0)
73+
74+
for o, v in opts:
75+
if o == '--help' or o == '-h':
76+
print(usage)
77+
sys.exit(0)
78+
elif o == '--all' or o == '-a':
79+
args = list(output_list_all)
80+
81+
output_list = set()
82+
83+
while len(args) != 0:
84+
pop = args.pop()
85+
if pop not in output_list_all:
86+
print('invalid args:{}'.format(pop))
87+
print(usage)
88+
sys.exit(2)
89+
output_list.add(pop)
90+
if pop in dependency_list:
91+
for d in dependency_list[pop]:
92+
args.append(d)
93+
94+
output_list = list(output_list)
95+
output_list.sort()
96+
97+
output_data = []
98+
for i in output_list:
99+
buf = output_file(i)
100+
output_data.extend(buf)
101+
102+
for i in output_list:
103+
# Modules that begin with 'internal' are for internal use, so they are not
104+
# declared.
105+
if not i.startswith('internal'):
106+
output_data.append('use {}::*;'.format(i))
107+
108+
# rustfmt
109+
with tempfile.TemporaryDirectory() as temp_dir:
110+
temp_file = temp_dir + '/output.rs'
111+
with open(temp_file, 'w') as f:
112+
print(output_header, file=f)
113+
for i in output_data:
114+
print(i, file=f)
115+
output_data = subprocess.run(["rustfmt", temp_file], check=True)
116+
with open(temp_file, 'r') as f:
117+
for line in f:
118+
print(line, end="")

0 commit comments

Comments
 (0)