This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.0 KiB

  1. #
  2. # This is a toy example that compiles Python directly to bytecode, without generating an AST.
  3. # It currently only works for very very simple Python code.
  4. #
  5. # It requires the 'bytecode' library. You can get it using
  6. #
  7. # $ pip install bytecode
  8. #
  9. from lark import Lark, Transformer, v_args
  10. from lark.indenter import Indenter
  11. from bytecode import Instr, Bytecode
  12. class PythonIndenter(Indenter):
  13. NL_type = '_NEWLINE'
  14. OPEN_PAREN_types = ['LPAR', 'LSQB', 'LBRACE']
  15. CLOSE_PAREN_types = ['RPAR', 'RSQB', 'RBRACE']
  16. INDENT_type = '_INDENT'
  17. DEDENT_type = '_DEDENT'
  18. tab_len = 8
  19. @v_args(inline=True)
  20. class Compile(Transformer):
  21. def number(self, n):
  22. return [Instr('LOAD_CONST', int(n))]
  23. def string(self, s):
  24. return [Instr('LOAD_CONST', s[1:-1])]
  25. def var(self, n):
  26. return [Instr('LOAD_NAME', n)]
  27. def arith_expr(self, a, op, b):
  28. # TODO support chain arithmetic
  29. assert op == '+'
  30. return a + b + [Instr('BINARY_ADD')]
  31. def arguments(self, args):
  32. return args
  33. def funccall(self, name, args):
  34. return name + args + [Instr('CALL_FUNCTION', 1)]
  35. @v_args(inline=False)
  36. def file_input(self, stmts):
  37. return sum(stmts, []) + [Instr("RETURN_VALUE")]
  38. def expr_stmt(self, lval, rval):
  39. # TODO more complicated than that
  40. name ,= lval
  41. assert name.name == 'LOAD_NAME' # XXX avoid with another layer of abstraction
  42. return rval + [Instr("STORE_NAME", name.arg)]
  43. def __default__(self, *args):
  44. assert False, args
  45. python_parser3 = Lark.open('python3.lark', rel_to=__file__, start='file_input',
  46. parser='lalr', postlex=PythonIndenter(),
  47. transformer=Compile(), propagate_positions=False)
  48. def compile_python(s):
  49. insts = python_parser3.parse(s+"\n")
  50. return Bytecode(insts).to_code()
  51. code = compile_python("""
  52. a = 3
  53. b = 5
  54. print("Hello World!")
  55. print(a+(b+2))
  56. print((a+b)+2)
  57. """)
  58. exec(code)
  59. # -- Output --
  60. # Hello World!
  61. # 10
  62. # 10