Guest User

Untitled

a guest
Oct 17th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.72 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, elidable, promote
  16.  
  17. class Rule(object):
  18.     """
  19.    a rule maps a variable to a tokens string
  20.    """
  21.     _immutable_=True
  22.    
  23.     variable = ""
  24.     tokens = ""
  25.    
  26.     def __init__(self, variable, tokens):
  27.         self.variable = variable
  28.         self.tokens = tokens
  29.  
  30.     def __str__(self):
  31.         return "%s : %s" % (self.variable, self.tokens)
  32.  
  33. class ScriptContext(object):
  34.     """
  35.    contains all context belonging to a script
  36.    """
  37.     _immutable_fields_ = [
  38.         "cairo_context", "cairo_surface",
  39.         "iterations", "start", "rules", "state"
  40.         ]
  41.    
  42.     cairo_context = 0L #SIZE_T
  43.     cairo_surface = 0L
  44.     iterations = 0
  45.     start = ""
  46.     rules = None
  47.     state = None
  48.  
  49.     @elidable
  50.     def get_rule(self, symbol):
  51.         return self.rules[symbol]
  52.    
  53.    
  54.     @elidable
  55.     def is_in_rules(self, symbol):
  56.         return symbol in self.rules
  57.  
  58.  
  59.  
  60. class DrawingState(object):
  61.     """
  62.    object to store drawing state information like
  63.    current pen position, color, direction, etc.
  64.    """
  65.     pos_x = 0.0
  66.     pos_y = 0.0
  67.     step = 2.0
  68.     angle = 0.0
  69.  
  70. ############ Sorry for the mess, here are some cairo-functions:
  71. from pypy.rpython.lltypesystem import rffi, lltype
  72. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  73.  
  74. 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")
  75. eci2 = ExternalCompilationInfo.from_linker_flags("-lcairo")
  76. eci3 = ExternalCompilationInfo(includes=["cairo.h"])
  77. info = eci1.merge(eci2)
  78. info = eci3.merge(info)
  79.  
  80.  
  81. cairo_image_surface_create = rffi.llexternal(
  82.     "cairo_image_surface_create",
  83.     [rffi.INT, rffi.INT, rffi.INT], rffi.SIZE_T,
  84.     compilation_info=info)
  85.  
  86. cairo_create = rffi.llexternal(
  87.     "cairo_create", [rffi.SIZE_T], rffi.SIZE_T,
  88.     compilation_info=info)
  89.  
  90. cairo_set_source_rgb = rffi.llexternal(
  91.     "cairo_set_source_rgb",
  92.     [rffi.SIZE_T, rffi.DOUBLE, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  93.     compilation_info=info)
  94.  
  95. cairo_paint = rffi.llexternal("cairo_paint", [rffi.SIZE_T], lltype.Void,
  96.     compilation_info=info)
  97.  
  98. cairo_move_to = rffi.llexternal(
  99.     "cairo_move_to",
  100.     [rffi.SIZE_T, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  101.     compilation_info=info)
  102.  
  103. cairo_line_to = rffi.llexternal(
  104.     "cairo_line_to",
  105.     [rffi.SIZE_T, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
  106.     compilation_info=info)
  107.  
  108. cairo_stroke = rffi.llexternal("cairo_stroke", [rffi.SIZE_T], lltype.Void,
  109.     compilation_info=info)
  110.  
  111. cairo_surface_write_to_png = rffi.llexternal(
  112.     "cairo_surface_write_to_png",
  113.     [rffi.SIZE_T, rffi.CCHARP], rffi.INT,
  114.     compilation_info=info)
  115.  
  116. cairo_surface_destroy = rffi.llexternal(
  117.     "cairo_surface_destroy",
  118.     [rffi.SIZE_T], lltype.Void,
  119.     compilation_info=info)
  120.  
  121. cairo_destroy = rffi.llexternal("cairo_destroy",
  122.                                 [rffi.SIZE_T], lltype.Void,
  123.                                 compilation_info=info)
  124.  
  125.  
  126. def get_location(depth, rule):
  127.     return "%s - %s" % (depth, rule.__str__())
  128.  
  129. jitdriver = JitDriver(
  130.     greens=['depth', 'rule'],
  131.     reds=['context'],
  132.     get_printable_location = get_location)
  133.  
  134.  
  135. def recurse_eval(rule, context, depth):
  136.     jitdriver.jit_merge_point(
  137.         depth = depth, rule = rule, context = context
  138.         )
  139.  
  140.     state = context.state
  141.     state = promote(state)
  142.     context = promote(context)
  143.    
  144.     for symbol in rule.tokens:
  145.        
  146.         if context.is_in_rules(symbol) and depth < context.iterations:
  147.             next_rule = context.get_rule(symbol)
  148.             recurse_eval(next_rule, context, depth + 1)
  149.         elif symbol == "+":
  150.             state.angle += math.pi / 2.0
  151.         elif symbol == "-":
  152.             state.angle -= math.pi / 2.0
  153.         elif symbol == "F":
  154.             state.pos_x = state.pos_x + math.cos(state.angle) * state.step
  155.             state.pos_y = state.pos_y + math.sin(state.angle) * state.step
  156.            
  157.             cairo_line_to(context.cairo_context,
  158.                           state.pos_x, state.pos_y)
  159.    
  160.  
  161. def mainloop(scriptctx):
  162.     scriptctx.cairo_surface = cairo_image_surface_create(0, WIDTH, HEIGHT)
  163.     scriptctx.cairo_context = cairo_create(scriptctx.cairo_surface)
  164.    
  165.     cairo_set_source_rgb(scriptctx.cairo_context, 0.0, 0.0, 0.0)
  166.     cairo_paint(scriptctx.cairo_context)
  167.     cairo_move_to(scriptctx.cairo_context, WIDTH / 2, HEIGHT / 2)
  168.  
  169.     scriptctx.state = DrawingState()
  170.     scriptctx.state.pos_x, scriptctx.state.pos_y = WIDTH / 2, HEIGHT / 2
  171.    
  172.     curr_rule = scriptctx.get_rule(scriptctx.start)
  173.  
  174.     recurse_eval(curr_rule, scriptctx, 0)
  175.    
  176.     cairo_set_source_rgb(scriptctx.cairo_context, 1.0, 1.0, 1.0)
  177.     cairo_stroke(scriptctx.cairo_context)
  178.     cairo_surface_write_to_png(scriptctx.cairo_surface, "out.png")
  179.     cairo_surface_destroy(scriptctx.cairo_surface)
  180.     cairo_destroy(scriptctx.cairo_context)
  181.    
  182. def parse(program):
  183.     iterations = 0
  184.     start = ""
  185.     rules = {}
  186.    
  187.     for line in program.split("\n"):
  188.         l = line.split(":")
  189.         if len(l) == 2:
  190.             lhs, rhs = l[0].strip(" "), l[1].strip(" ")
  191.  
  192.             if lhs == "iterations":
  193.                 iterations = int(rhs)
  194.             elif lhs == "start":
  195.                 start = rhs
  196.             elif lhs != "":
  197.                 r = Rule(lhs, rhs)
  198.                 rules[lhs] = r
  199.  
  200.     return iterations, start, rules
  201.  
  202.  
  203. def run(fp):
  204.     program_contents = ""
  205.     while True:
  206.         read = os.read(fp, 4096)
  207.         if len(read) == 0:
  208.             break
  209.         program_contents += read
  210.     os.close(fp)
  211.    
  212.     iterations, start, rules = parse(program_contents)
  213.  
  214.     script_context = ScriptContext()
  215.     script_context.iterations = iterations
  216.     script_context.start = start
  217.     script_context.rules = rules
  218.    
  219.     mainloop(script_context)
  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