Skip to content

Commit 163237c

Browse files
chaemonkyuridenamida
authored andcommitted
NIM言語を追加 (kyuridenamida#146)
* add nim * add nim tests * add nim to .travis.yml * changed to pass pep8 * erase comment out * erase comment out
1 parent 24f6008 commit 163237c

File tree

15 files changed

+661
-8
lines changed

15 files changed

+661
-8
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ python:
88
before_install:
99
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y # for C++14
1010
- sudo apt-get update
11-
- sudo apt-get install rustc g++-4.9 openjdk-8-jdk
11+
- sudo apt-get install rustc g++-4.9 openjdk-8-jdk nim
1212
- sudo ln -f -s /usr/bin/g++-4.9 /usr/bin/g++
1313

1414
install:
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
from typing import Dict, Any, Optional
2+
3+
from atcodertools.codegen.code_style_config import CodeStyleConfig
4+
from atcodertools.codegen.models.code_gen_args import CodeGenArgs
5+
from atcodertools.codegen.template_engine import render
6+
from atcodertools.fmtprediction.models.format import Pattern, SingularPattern, ParallelPattern, TwoDimensionalPattern, \
7+
Format
8+
from atcodertools.fmtprediction.models.type import Type
9+
from atcodertools.fmtprediction.models.variable import Variable
10+
11+
12+
def _loop_header(var: Variable, for_second_index: bool):
13+
if for_second_index:
14+
index = var.second_index
15+
loop_var = "j"
16+
else:
17+
index = var.first_index
18+
loop_var = "i"
19+
20+
return "for {loop_var} in 0..<{length}:".format(
21+
loop_var=loop_var,
22+
length=index.get_length()
23+
)
24+
25+
26+
class NimCodeGenerator:
27+
28+
def __init__(self,
29+
format_: Optional[Format[Variable]],
30+
config: CodeStyleConfig):
31+
self._format = format_
32+
self._config = config
33+
34+
def generate_parameters(self) -> Dict[str, Any]:
35+
if self._format is None:
36+
return dict(prediction_success=False)
37+
38+
return dict(formal_arguments=self._formal_arguments(),
39+
actual_arguments=self._actual_arguments(),
40+
input_part=self._input_part(),
41+
prediction_success=True)
42+
43+
def _input_part(self):
44+
lines = []
45+
for pattern in self._format.sequence:
46+
lines += self._render_pattern(pattern)
47+
return "\n{indent}".format(indent=self._indent(1)).join(lines)
48+
49+
def _convert_type(self, type_: Type) -> str:
50+
if type_ == Type.float:
51+
return "float"
52+
elif type_ == Type.int:
53+
return "int"
54+
elif type_ == Type.str:
55+
return "string"
56+
else:
57+
raise NotImplementedError
58+
59+
def _default_val(self, type_: Type) -> str:
60+
if type_ == Type.float:
61+
return "0.0"
62+
elif type_ == Type.int:
63+
return "0"
64+
elif type_ == Type.str:
65+
return "\"\""
66+
else:
67+
raise NotImplementedError
68+
69+
def _get_declaration_type(self, var: Variable):
70+
ctype = self._convert_type(var.type)
71+
for _ in range(var.dim_num()):
72+
ctype = 'seq[{}]'.format(ctype)
73+
return ctype
74+
75+
def _actual_arguments(self) -> str:
76+
"""
77+
:return the string form of actual arguments e.g. "N, K, a"
78+
"""
79+
return ", ".join([
80+
v.name if v.dim_num() == 0 else '{}'.format(v.name)
81+
for v in self._format.all_vars()])
82+
83+
def _formal_arguments(self):
84+
"""
85+
:return the string form of formal arguments e.g. "int N, int K, std::vector<int> a"
86+
"""
87+
return ", ".join([
88+
"{name}:{decl_type}".format(
89+
decl_type=self._get_declaration_type(v),
90+
name=v.name)
91+
for v in self._format.all_vars()
92+
])
93+
94+
def _generate_declaration(self, var: Variable):
95+
"""
96+
:return: Create declaration part E.g. array[1..n] -> std::vector<int> array = std::vector<int>(n-1+1);
97+
"""
98+
if var.dim_num() == 0:
99+
dims = []
100+
elif var.dim_num() == 1:
101+
dims = [var.first_index.get_length()]
102+
elif var.dim_num() == 2:
103+
dims = [var.first_index.get_length(),
104+
var.second_index.get_length()]
105+
else:
106+
raise NotImplementedError
107+
e = self._default_val(var.type)
108+
for dim in dims[::-1]:
109+
e = "newSeqWith({}, {})".format(dim, e)
110+
return "var {name} = {expression}".format(name=var.name, expression=e)
111+
112+
def _input_code_for_var(self, var: Variable) -> str:
113+
name = self._get_var_name(var)
114+
if var.type == Type.float:
115+
return '{name} = nextFloat()'.format(name=name)
116+
elif var.type == Type.int:
117+
return '{name} = nextInt()'.format(name=name)
118+
elif var.type == Type.str:
119+
return '{name} = nextString()'.format(name=name)
120+
else:
121+
raise NotImplementedError
122+
123+
@staticmethod
124+
def _get_var_name(var: Variable):
125+
name = var.name
126+
if var.dim_num() >= 1:
127+
name += "[i]"
128+
if var.dim_num() >= 2:
129+
name += "[j]"
130+
return name
131+
132+
def _render_pattern(self, pattern: Pattern):
133+
lines = []
134+
for var in pattern.all_vars():
135+
lines.append(self._generate_declaration(var))
136+
137+
representative_var = pattern.all_vars()[0]
138+
if isinstance(pattern, SingularPattern):
139+
lines.append(self._input_code_for_var(representative_var))
140+
elif isinstance(pattern, ParallelPattern):
141+
lines.append(_loop_header(representative_var, False))
142+
for var in pattern.all_vars():
143+
lines.append("{indent}{line}".format(indent=self._indent(1),
144+
line=self._input_code_for_var(var)))
145+
elif isinstance(pattern, TwoDimensionalPattern):
146+
lines.append(_loop_header(representative_var, False))
147+
lines.append(
148+
"{indent}{line}".format(indent=self._indent(1), line=_loop_header(representative_var, True)))
149+
for var in pattern.all_vars():
150+
lines.append("{indent}{line}".format(indent=self._indent(2),
151+
line=self._input_code_for_var(var)))
152+
else:
153+
raise NotImplementedError
154+
155+
return lines
156+
157+
def _indent(self, depth):
158+
return self._config.indent(depth)
159+
160+
161+
class NoPredictionResultGiven(Exception):
162+
pass
163+
164+
165+
def main(args: CodeGenArgs) -> str:
166+
code_parameters = NimCodeGenerator(
167+
args.format, args.config).generate_parameters()
168+
return render(
169+
args.template,
170+
mod=args.constants.mod,
171+
yes_str=args.constants.yes_str,
172+
no_str=args.constants.no_str,
173+
**code_parameters
174+
)

atcodertools/common/language.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import re
22
from typing import Pattern, Callable
33

4-
from atcodertools.codegen.code_generators import cpp, java, rust, python
4+
from atcodertools.codegen.code_generators import cpp, java, rust, python, nim
55
from atcodertools.codegen.models.code_gen_args import CodeGenArgs
66
from atcodertools.tools.templates import get_default_template_path
77

@@ -76,5 +76,14 @@ def from_name(cls, name: str):
7676
default_template_path=get_default_template_path('py'),
7777
)
7878

79-
ALL_LANGUAGES = [CPP, JAVA, RUST, PYTHON]
79+
NIM = Language(
80+
name="nim",
81+
display_name="NIM",
82+
extension="nim",
83+
submission_lang_pattern=re.compile(".*Nim \\(0.*"),
84+
default_code_generator=nim.main,
85+
default_template_path=get_default_template_path('nim'),
86+
)
87+
88+
ALL_LANGUAGES = [CPP, JAVA, RUST, PYTHON, NIM]
8089
ALL_LANGUAGE_NAMES = [lang.display_name for lang in ALL_LANGUAGES]
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import sequtils
2+
proc scanf(formatstr: cstring){.header: "<stdio.h>", varargs.}
3+
proc getchar(): char {.header: "<stdio.h>", varargs.}
4+
proc nextInt(): int = scanf("%lld",addr result)
5+
proc nextFloat(): float = scanf("%lf",addr result)
6+
proc nextString(): string =
7+
var get = false
8+
result = ""
9+
while true:
10+
var c = getchar()
11+
if int(c) > int(' '):
12+
get = true
13+
result.add(c)
14+
else:
15+
if get: break
16+
get = false
17+
18+
{% if mod %}
19+
let MOD = {{ mod }}
20+
{% endif %}
21+
{% if yes_str %}
22+
let YES = "{{ yes_str }}"
23+
{% endif %}
24+
{% if no_str %}
25+
let NO = "{{ no_str }}"
26+
{% endif %}
27+
28+
{% if prediction_success %}
29+
proc solve({{ formal_arguments }}):void =
30+
discard
31+
{% endif %}
32+
33+
proc main():void =
34+
{% if prediction_success %}
35+
{{input_part}}
36+
solve({{ actual_arguments }});
37+
{% else %}
38+
# Failed to predict input format
39+
{% endif %}
40+
return
41+
42+
main()
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import sequtils
2+
proc scanf(formatstr: cstring){.header: "<stdio.h>", varargs.}
3+
proc getchar(): char {.header: "<stdio.h>", varargs.}
4+
proc nextInt(): int = scanf("%lld",addr result)
5+
proc nextFloat(): float = scanf("%lf",addr result)
6+
proc nextString(): string =
7+
var get = false
8+
result = ""
9+
while true:
10+
var c = getchar()
11+
if int(c) > int(' '):
12+
get = true
13+
result.add(c)
14+
else:
15+
if get: break
16+
17+
proc solve(${formal_arguments}):void =
18+
return
19+
20+
proc main():void =
21+
${input_part}
22+
solve(${actual_arguments})
23+
return
24+
25+
main()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import sequtils
2+
proc scanf(formatstr: cstring){.header: "<stdio.h>", varargs.}
3+
proc getchar(): char {.header: "<stdio.h>", varargs.}
4+
proc nextInt(): int = scanf("%lld",addr result)
5+
proc nextFloat(): float = scanf("%lf",addr result)
6+
proc nextString(): string =
7+
var get = false
8+
result = ""
9+
while true:
10+
var c = getchar()
11+
if int(c) > int(' '):
12+
get = true
13+
result.add(c)
14+
else:
15+
if get: break
16+
17+
{% if mod %}
18+
let MOD = {{ mod }}
19+
{% endif %}
20+
{% if yes_str %}
21+
let YES = "{{ yes_str }}"
22+
{% endif %}
23+
{% if no_str %}
24+
let NO = "{{ no_str }}"
25+
{% endif %}
26+
27+
proc solve({{ formal_arguments }}):void =
28+
return
29+
30+
proc main():void =
31+
{{input_part}}
32+
solve({{ actual_arguments }})
33+
return
34+
35+
main()
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import sequtils
2+
proc scanf(formatstr: cstring){.header: "<stdio.h>", varargs.}
3+
proc getchar(): char {.header: "<stdio.h>", varargs.}
4+
proc nextInt(): int = scanf("%lld",addr result)
5+
proc nextFloat(): float = scanf("%lf",addr result)
6+
proc nextString(): string =
7+
var get = false
8+
result = ""
9+
while true:
10+
var c = getchar()
11+
if int(c) > int(' '):
12+
get = true
13+
result.add(c)
14+
else:
15+
if get: break
16+
get = false
17+
18+
{% if mod %}
19+
let MOD = {{ mod }}
20+
{% endif %}
21+
{% if yes_str %}
22+
let YES = "{{ yes_str }}"
23+
{% endif %}
24+
{% if no_str %}
25+
let NO = "{{ no_str }}"
26+
{% endif %}
27+
28+
proc solve({{ formal_arguments }}):void =
29+
echo N," ",M
30+
assert H.len == N - 1
31+
for i in 0..<N-1:
32+
assert H[i].len == M - 2
33+
for j in 0..<M-2:
34+
stdout.write if j > 0: " " else:"", H[i][j]
35+
echo ""
36+
assert A.len == N - 1
37+
assert B.len == N - 1
38+
for i in 0..<N-1:
39+
echo A[i]," ",B[i]
40+
echo Q
41+
assert X.len == M + Q
42+
for i in 0..<M + Q:
43+
echo X[i]
44+
echo YES
45+
echo NO
46+
echo MOD
47+
48+
proc main():void =
49+
{{input_part}}
50+
solve({{ actual_arguments }})
51+
return
52+
53+
main()

0 commit comments

Comments
 (0)