Guest User

Untitled

a guest
Oct 17th, 2017
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.87 KB | None | 0 0
  1. """
  2. L-Systems interpreter based on Andrew Brown's excellent tutorial:
  3.  
  4. PyPy tutorial by Andrew Brown
  5. example5.py - BF interpreter in RPython, translatable by PyPy, with JIT, and
  6.              with a get_printable_location function and pure function wrapper
  7.              for the dictionary lookup.
  8. """
  9. WIDTH = 800
  10. HEIGHT = 600
  11.  
  12. import os
  13. import sys
  14. import math
  15. from pypy.rlib.jit import JitDriver, purefunction
  16.  
  17. class Rule(object):
  18.     """
  19.    a rule maps a variable to a tokens string
  20.    """
  21.     variable = ""
  22.     tokens = ""
  23.    
  24.     def __init__(self, variable, tokens):
  25.         self.variable = variable
  26.         self.tokens = tokens
  27.  
  28.     def __str__(self):
  29.         return "%s : %s" % (self.variable, self.tokens)
  30.  
  31. class DrawingState(object):
  32.     """
  33.    object to store drawing state information like
  34.    current pen position, color, direction, etc.
  35.    """
  36.     pos = (0.0, 0.0)
  37.     step = 2.0
  38.     angle = 0.0
  39.  
  40. ############ Sorry for the mess, here are some cairo-functions:
  41. from pypy.rpython.lltypesystem import rffi, lltype
  42. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  43.  
  44. eci1 = ExternalCompilationInfo.from_compiler_flags("-pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/cairo -I/usr/include/pixman-1")
  45. eci2 = ExternalCompilationInfo.from_linker_flags("-lcairo")
  46. eci3 = ExternalCompilationInfo(includes=["cairo.h"])
  47. info = eci1.merge(eci2)
  48. info = eci3.merge(info)
  49.  
  50.  
  51. cairo_image_surface_create = rffi.llexternal(
  52.     "cairo_image_surface_create",
  53.     [rffi.INT, rffi.INT, rffi.INT], rffi.VOIDP,
  54.     compilation_info=info)
  55.  
  56. cairo_create = rffi.llexternal(
  57.     "cairo_create", [rffi.VOIDP], rffi.VOIDP,
  58.     compilation_info=info)
  59.  
  60. cairo_set_source_rgb = rffi.llexternal(
  61.     "cairo_set_source_rgb",
  62.     [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  63.     compilation_info=info)
  64.  
  65. cairo_paint = rffi.llexternal("cairo_paint", [rffi.VOIDP], lltype.Void,
  66.     compilation_info=info)
  67.  
  68. cairo_move_to = rffi.llexternal(
  69.     "cairo_move_to",
  70.     [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  71.     compilation_info=info)
  72.  
  73. cairo_line_to = rffi.llexternal(
  74.     "cairo_line_to",
  75.     [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  76.     compilation_info=info)
  77.  
  78. cairo_stroke = rffi.llexternal("cairo_stroke", [rffi.VOIDP], lltype.Void,
  79.     compilation_info=info)
  80.  
  81. cairo_surface_write_to_png = rffi.llexternal(
  82.     "cairo_surface_write_to_png",
  83.     [rffi.VOIDP, rffi.CCHARP], rffi.INT,
  84.     compilation_info=info)
  85.  
  86. cairo_surface_destroy = rffi.llexternal(
  87.     "cairo_surface_destroy",
  88.     [rffi.VOIDP], lltype.Void,
  89.     compilation_info=info)
  90.  
  91. cairo_destroy = rffi.llexternal("cairo_destroy",
  92.                                 [rffi.VOIDP], lltype.Void,
  93.                                 compilation_info=info)
  94.  
  95.  
  96. def get_location(depth, curr_pos, iterations, surface, context,
  97.             rules, curr_rule):
  98.     return "%s_%s_%s" % (
  99.         depth, curr_rule.__str__(), curr_pos
  100.         )
  101.  
  102. jitdriver = JitDriver(
  103.     greens=['depth', 'curr_pos', 'iterations', 'surface', 'context',
  104.             'rules', 'curr_rule',
  105.             ],
  106.     reds=['state', 'exec_stack'],
  107.     get_printable_location=get_location)
  108.  
  109.  
  110. @purefunction
  111. def get_rule(rules, symbol):
  112.     return rules[symbol]
  113.  
  114.  
  115. @purefunction
  116. def is_in_rules(rules, symbol):
  117.     return symbol in rules
  118.  
  119. def mainloop(iterations, start, rules):
  120.     surface = cairo_image_surface_create(0, WIDTH, HEIGHT)
  121.     context = cairo_create(surface)
  122.     cairo_set_source_rgb(context, 0.0, 0.0, 0.0)
  123.     cairo_paint(context)
  124.     cairo_move_to(context, WIDTH / 2, HEIGHT / 2)
  125.  
  126.     state = DrawingState()
  127.     state.pos = (WIDTH / 2, HEIGHT / 2)
  128.    
  129.     exec_stack = []
  130.     depth = 0
  131.  
  132.     curr_rule = get_rule(rules, start)
  133.     curr_pos = 0
  134.    
  135.     while True:
  136.         jitdriver.jit_merge_point(
  137.             depth=depth, curr_pos=curr_pos, iterations=iterations,
  138.             surface=surface, context=context,
  139.             rules=rules, exec_stack=exec_stack,
  140.             curr_rule=curr_rule,
  141.             state=state)
  142.    
  143.         if curr_pos >= len(curr_rule.tokens):
  144.             if len(exec_stack) == 0:
  145.                 stop = True
  146.                 break
  147.             else:
  148.                 curr_rule, curr_pos = exec_stack.pop()
  149.                 curr_pos += 1
  150.                 depth -= 1
  151.  
  152.                 jitdriver.can_enter_jit(
  153.                     depth=depth, curr_pos=curr_pos, iterations=iterations,
  154.                     surface=surface, context=context,
  155.                     rules=rules, exec_stack=exec_stack,
  156.                     curr_rule=curr_rule,
  157.                     state=state)
  158.                 continue
  159.  
  160.        
  161.         symbol = curr_rule.tokens[curr_pos]
  162.  
  163.         if is_in_rules(rules, symbol) and depth < iterations:
  164.             depth += 1
  165.             exec_stack.append((curr_rule, curr_pos))
  166.             curr_rule, curr_pos = get_rule(rules, symbol), -1
  167.             # curr_pos will be incremented _always_
  168.         elif symbol == "+":
  169.             state.angle += math.pi / 2.0
  170.         elif symbol == "-":
  171.             state.angle -= math.pi / 2.0
  172.         elif symbol == "F":
  173.             state.pos = (state.pos[0] + math.cos(state.angle) * state.step,
  174.                         state.pos[1] + math.sin(state.angle) * state.step)
  175.             cairo_line_to(context, state.pos[0], state.pos[1])
  176.         else:
  177.             pass
  178.        
  179.         curr_pos += 1
  180.  
  181.     cairo_set_source_rgb(context, 1.0, 1.0, 1.0)
  182.     cairo_stroke(context)
  183.     cairo_surface_write_to_png(surface, "out.png")
  184.     cairo_surface_destroy(surface)
  185.     cairo_destroy(context)
  186.    
  187. def parse(program):
  188.     iterations = 0
  189.     start = ""
  190.     rules = {}
  191.    
  192.     for line in program.split("\n"):
  193.         l = line.split(":")
  194.         if len(l) == 2:
  195.             lhs, rhs = l[0].strip(" "), l[1].strip(" ")
  196.  
  197.             if lhs == "iterations":
  198.                 iterations = int(rhs)
  199.             elif lhs == "start":
  200.                 start = rhs
  201.             elif lhs != "":
  202.                 r = Rule(lhs, rhs)
  203.                 rules[lhs] = r
  204.  
  205.     return iterations, start, rules
  206.  
  207.  
  208. def run(fp):
  209.     program_contents = ""
  210.     while True:
  211.         read = os.read(fp, 4096)
  212.         if len(read) == 0:
  213.             break
  214.         program_contents += read
  215.     os.close(fp)
  216.    
  217.     iterations, start, rules = parse(program_contents)
  218.    
  219.     mainloop(iterations, start, rules)
  220.  
  221. def entry_point(argv):
  222.     try:
  223.         filename = argv[1]
  224.     except IndexError:
  225.         print "You must supply a filename"
  226.         return 1
  227.    
  228.     run(os.open(filename, os.O_RDONLY, 0777))
  229.     return 0
  230.  
  231. def target(*args):
  232.     return entry_point, None
  233.    
  234. def jitpolicy(driver):
  235.     from pypy.jit.codewriter.policy import JitPolicy
  236.     return JitPolicy()
  237.  
  238. if __name__ == "__main__":
  239.     entry_point(sys.argv)
Add Comment
Please, Sign In to add comment