Last active
July 7, 2022 23:09
-
-
Save tekknolagi/97e5fb0e91013833a9a2525a3f05a21d to your computer and use it in GitHub Desktop.
A small Python to C compiler...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ast | |
import sys | |
import json | |
NoSemicolon = True | |
class CompileError(Exception): | |
pass | |
class DeclarationVisitor(ast.NodeVisitor): | |
def __init__(self): | |
super().__init__() | |
# name -> [type] | |
self.declarations = {} | |
def _declare(self, name, type): | |
if name in self.declarations: | |
self.declarations.append(type) | |
else: | |
self.declarations[name] = [type] | |
def visit_Assign(self, node): | |
for target in node.targets: | |
self._declare(target.id, "RawObject") | |
class Compiler(ast.NodeVisitor): | |
def __init__(self, stream): | |
super().__init__() | |
self.stream = stream | |
self.sym_counter = 0 | |
def _write(self, *args): | |
for arg in args: | |
print(arg, file=self.stream, end=" ") | |
def _writeline(self, *args): | |
for arg in args: | |
print(arg, file=self.stream, end=" ") | |
print(file=self.stream) | |
def _gensym(self): | |
current = self.sym_counter | |
self.sym_counter += 1 | |
return f"v{current}" | |
def visit_Assign(self, node): | |
value = self._gensym() | |
self._write("Object", value, "(&scope, ") | |
self.visit(node.value) | |
self._writeline(");") | |
for target in node.targets: | |
self._writeline(target.id, "=", value, ";") | |
return NoSemicolon | |
def visit_Num(self, node): | |
self._write(node.n) | |
def visit_Str(self, node): | |
# This will get us double quotes | |
self._write(json.dumps(node.s)) | |
def visit_BinOp(self, node): | |
assert isinstance(node.op, ast.Add) | |
self.visit(node.left) | |
self._write("+") | |
self.visit(node.right) | |
def visit_Return(self, node): | |
self._write("return ") | |
self.visit(node.value) | |
def visit_Import(self, node): | |
for name in node.names: | |
self._writeline(f"#include <{name.name}>") | |
return NoSemicolon | |
def visit_Name(self, node): | |
self._write(node.id) | |
def visit_Call(self, node): | |
assert isinstance(node.func, ast.Name) | |
assert not node.keywords | |
self.visit(node.func) | |
self._write("(") | |
first = True | |
for arg in node.args: | |
if not first: | |
self._write(", ") | |
first = False | |
self.visit(arg) | |
self._write(")") | |
def visit_FunctionDef(self, node): | |
assert not node.args.defaults | |
assert not node.args.kw_defaults | |
assert not node.args.kwonlyargs | |
declaration_visitor = DeclarationVisitor() | |
declaration_visitor.visit(node) | |
return_type = node.returns.id if node.returns else "void" | |
args = [f"const Object& {arg.arg}" for arg in node.args.args] | |
joined_args = ", " + ", ".join(args) if args else "" | |
self._writeline(f"{return_type} {node.name}(Thread* thread{joined_args}) {{") | |
self._writeline("HandleScope scope(thread);") | |
for name, types in declaration_visitor.declarations.items(): | |
self._writeline(f"Object {name}(&scope, NoneType::object());") | |
self._visit_block(node.body) | |
self._writeline("}") | |
return NoSemicolon | |
def _visit_block(self, body): | |
for stmt in body: | |
if self.visit(stmt) != NoSemicolon: | |
self._writeline(";") | |
def visit_Module(self, node): | |
self._visit_block(node.body) | |
if __name__ == "__main__": | |
filename = sys.argv[1] | |
with open(filename) as f: | |
tree = ast.parse(f.read(), filename, "exec") | |
Compiler(sys.stdout).visit(tree) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def foo(x, y) -> RawObject: | |
return x + y | |
def bar(x) -> RawObject: | |
return x | |
def main() -> int: | |
x = bar(foo(1, 2)) | |
print(x) | |
return 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment