mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-07 00:21:07 +01:00
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/42629 How to approach reviewing this diff: - The new codegen itself lives in `tools/codegen`. Start with `gen.py`, then read `model.py` and them the `api/` folder. The comments at the top of the files describe what is going on. The CLI interface of the new codegen is similar to the old one, but (1) it is no longer necessary to explicitly specify cwrap inputs (and now we will error if you do so) and (2) the default settings for source and install dir are much better; to the extent that if you run the codegen from the root source directory as just `python -m tools.codegen.gen`, something reasonable will happen. - The old codegen is (nearly) entirely deleted; every Python file in `aten/src/ATen` was deleted except for `common_with_cwrap.py`, which now permanently finds its home in `tools/shared/cwrap_common.py` (previously cmake copied the file there), and `code_template.py`, which now lives in `tools/codegen/code_template.py`. We remove the copying logic for `common_with_cwrap.py`. - All of the inputs to the old codegen are deleted. - Build rules now have to be adjusted to not refer to files that no longer exist, and to abide by the (slightly modified) CLI. - LegacyTHFunctions files have been generated and checked in. We expect these to be deleted as these final functions get ported to ATen. The deletion process is straightforward; just delete the functions of the ones you are porting. There are 39 more functions left to port. Signed-off-by: Edward Z. Yang <ezyang@fb.com> Test Plan: Imported from OSS Reviewed By: bhosmer Differential Revision: D23183978 Pulled By: ezyang fbshipit-source-id: 6073ba432ad182c7284a97147b05f0574a02f763
92 lines
3.1 KiB
Python
92 lines
3.1 KiB
Python
import re
|
|
from typing import Match, Optional, Sequence, Mapping
|
|
|
|
# match $identifier or ${identifier} and replace with value in env
|
|
# If this identifier is at the beginning of whitespace on a line
|
|
# and its value is a list then it is treated as
|
|
# block substitution by indenting to that depth and putting each element
|
|
# of the list on its own line
|
|
# if the identifier is on a line starting with non-whitespace and a list
|
|
# then it is comma separated ${,foo} will insert a comma before the list
|
|
# if this list is not empty and ${foo,} will insert one after.
|
|
|
|
|
|
class CodeTemplate:
|
|
# Python 2.7.5 has a bug where the leading (^[^\n\S]*)? does not work,
|
|
# workaround via appending another [^\n\S]? inside
|
|
|
|
substitution_str = r'(^[^\n\S]*[^\n\S]?)?\$([^\d\W]\w*|\{,?[^\d\W]\w*\,?})'
|
|
|
|
# older versions of Python have a bug where \w* does not work,
|
|
# so we need to replace with the non-shortened version [a-zA-Z0-9_]*
|
|
# https://bugs.python.org/issue18647
|
|
|
|
substitution_str = substitution_str.replace(r'\w', r'[a-zA-Z0-9_]')
|
|
|
|
substitution = re.compile(substitution_str, re.MULTILINE)
|
|
|
|
pattern: str
|
|
filename: str
|
|
|
|
@staticmethod
|
|
def from_file(filename: str) -> 'CodeTemplate':
|
|
with open(filename, 'r') as f:
|
|
return CodeTemplate(f.read(), filename)
|
|
|
|
def __init__(self, pattern: str, filename: str = "") -> None:
|
|
self.pattern = pattern
|
|
self.filename = filename
|
|
|
|
def substitute(self, env: Optional[Mapping[str, object]] = None, **kwargs: object) -> str:
|
|
if env is None:
|
|
env = {}
|
|
|
|
def lookup(v: str) -> object:
|
|
assert env is not None
|
|
return kwargs[v] if v in kwargs else env[v]
|
|
|
|
def indent_lines(indent: str, v: Sequence[object]) -> str:
|
|
return "".join([indent + l + "\n" for e in v for l in str(e).splitlines()]).rstrip()
|
|
|
|
def replace(match: Match[str]) -> str:
|
|
indent = match.group(1)
|
|
key = match.group(2)
|
|
comma_before = ''
|
|
comma_after = ''
|
|
if key[0] == "{":
|
|
key = key[1:-1]
|
|
if key[0] == ",":
|
|
comma_before = ', '
|
|
key = key[1:]
|
|
if key[-1] == ',':
|
|
comma_after = ', '
|
|
key = key[:-1]
|
|
v = lookup(key)
|
|
if indent is not None:
|
|
if not isinstance(v, list):
|
|
v = [v]
|
|
return indent_lines(indent, v)
|
|
elif isinstance(v, list):
|
|
middle = ', '.join([str(x) for x in v])
|
|
if len(v) == 0:
|
|
return middle
|
|
return comma_before + middle + comma_after
|
|
else:
|
|
return str(v)
|
|
return self.substitution.sub(replace, self.pattern)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
c = CodeTemplate("""\
|
|
int foo($args) {
|
|
|
|
$bar
|
|
$bar
|
|
$a+$b
|
|
}
|
|
int commatest(int a${,stuff})
|
|
int notest(int a${,empty,})
|
|
""")
|
|
print(c.substitute(args=["hi", 8], bar=["what", 7],
|
|
a=3, b=4, stuff=["things...", "others"], empty=[]))
|