Skip to content

Instantly share code, notes, and snippets.

@wangkuiyi
Created January 29, 2023 06:32
Show Gist options
  • Select an option

  • Save wangkuiyi/f57de13df6fa7a32abd8968c8509e397 to your computer and use it in GitHub Desktop.

Select an option

Save wangkuiyi/f57de13df6fa7a32abd8968c8509e397 to your computer and use it in GitHub Desktop.
Converts a Python script that prints an MLIR into a Markdown section
# Run the following command to convert 01-double.py into a Markdown section.
#
# python interweave_python_mlir.py python_file
#
# Requirements:
#
# 1. Running the python_file must prints the MLIR source code.
#
# 2. If there is a comments of a number before a Python code block in
# python_file, the number is the number of lines of the MLIR source
# code should be matched with the Python code block.
#
# Outputs:
#
# 1. The Markdown section header is the script file name.
#
# 2. The section content is the content of the multi-line string at
# the beginning of the Python script file, if there is one.
#
# 3. The following table typesets interweaved content from python_file
# and the MLIR source code.
#
from typing import List, Tuple
def capture_stdout(python_script: str) -> List[str]:
""" Execute a Python script, capture the stdout, and split it by lines. """
import subprocess
process = subprocess.Popen(["python", python_script], stdout=subprocess.PIPE)
(output, err) = process.communicate()
if process.wait() < 0:
raise Exception(f"capture_stdout failed with {err.decode('utf-8')}")
return output.decode('utf-8').split('\n')
def is_end_of_block(line: str) -> Tuple[bool, int]:
""" Returns (true, 0) if line is empty, or (true, n) if line comments a number n """
line = line.strip()
if line == "":
return (True, 0)
if line[0] == '#' and line[1:].strip().isdigit():
return (True, int(line[1:]))
return (False, 0)
def is_multiline_string_quote(line: str) -> bool:
return line.strip() == '"""'
def weave(py_buf: List[str], mlir_lines: List[str], emitted: int, to_emit: int):
print("<tr><td>")
print("```")
for l in py_buf:
print(l, end="")
print("```")
if to_emit == 0:
print("</td></tr>")
return
print("</td><td>")
print("```")
for i in range(emitted, emitted + to_emit):
print(mlir_lines[i])
print("```")
print("</td></tr>")
BEGIN = 0
PREAMBLE = 1
WEAVING = 2
def switch_to(to: int) -> int:
if to == WEAVING:
print()
print("<table>")
return to
def interweave(python_script: str) -> str:
mlir_lines = capture_stdout(python_script)
py_buf: List[str] = [] # the current Python code block.
num_mlir_lines = 0 # the number of MLIR lines of the current block
emitted_mlir_lines = 0
with open(python_script) as py:
print(f"## {python_script}\n")
state: int = BEGIN
while (line := py.readline()):
if state == BEGIN:
if is_multiline_string_quote(line):
state = switch_to(PREAMBLE)
else:
state = switch_to(WEAVING)
elif state == PREAMBLE:
if is_multiline_string_quote(line):
state = switch_to(WEAVING)
else:
print(line)
elif state == WEAVING:
sep, n = is_end_of_block(line)
if sep:
weave(py_buf, mlir_lines, emitted_mlir_lines, num_mlir_lines)
py_buf = []
emitted_mlir_lines += num_mlir_lines
num_mlir_lines = n
else:
py_buf.append(line)
print("</table>")
import sys
interweave(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment