Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- L-Systems interpreter based on Andrew Brown's excellent tutorial:
- PyPy tutorial by Andrew Brown
- example5.py - BF interpreter in RPython, translatable by PyPy, with JIT, and
- with a get_printable_location function and pure function wrapper
- for the dictionary lookup.
- """
- WIDTH = 800
- HEIGHT = 600
- import os
- import sys
- import math
- from pypy.rlib.jit import JitDriver, purefunction
- class Rule(object):
- """
- a rule maps a variable to a tokens string
- """
- variable = ""
- tokens = ""
- def __init__(self, variable, tokens):
- self.variable = variable
- self.tokens = tokens
- def __str__(self):
- return "%s : %s" % (self.variable, self.tokens)
- class DrawingState(object):
- """
- object to store drawing state information like
- current pen position, color, direction, etc.
- """
- pos = (0.0, 0.0)
- step = 2.0
- angle = 0.0
- ############ Sorry for the mess, here are some cairo-functions:
- from pypy.rpython.lltypesystem import rffi, lltype
- from pypy.translator.tool.cbuild import ExternalCompilationInfo
- 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")
- eci2 = ExternalCompilationInfo.from_linker_flags("-lcairo")
- eci3 = ExternalCompilationInfo(includes=["cairo.h"])
- info = eci1.merge(eci2)
- info = eci3.merge(info)
- cairo_image_surface_create = rffi.llexternal(
- "cairo_image_surface_create",
- [rffi.INT, rffi.INT, rffi.INT], rffi.VOIDP,
- compilation_info=info)
- cairo_create = rffi.llexternal(
- "cairo_create", [rffi.VOIDP], rffi.VOIDP,
- compilation_info=info)
- cairo_set_source_rgb = rffi.llexternal(
- "cairo_set_source_rgb",
- [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
- compilation_info=info)
- cairo_paint = rffi.llexternal("cairo_paint", [rffi.VOIDP], lltype.Void,
- compilation_info=info)
- cairo_move_to = rffi.llexternal(
- "cairo_move_to",
- [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
- compilation_info=info)
- cairo_line_to = rffi.llexternal(
- "cairo_line_to",
- [rffi.VOIDP, rffi.DOUBLE, rffi.DOUBLE], lltype.Void,
- compilation_info=info)
- cairo_stroke = rffi.llexternal("cairo_stroke", [rffi.VOIDP], lltype.Void,
- compilation_info=info)
- cairo_surface_write_to_png = rffi.llexternal(
- "cairo_surface_write_to_png",
- [rffi.VOIDP, rffi.CCHARP], rffi.INT,
- compilation_info=info)
- cairo_surface_destroy = rffi.llexternal(
- "cairo_surface_destroy",
- [rffi.VOIDP], lltype.Void,
- compilation_info=info)
- cairo_destroy = rffi.llexternal("cairo_destroy",
- [rffi.VOIDP], lltype.Void,
- compilation_info=info)
- def get_location(depth, curr_pos, iterations, surface, context,
- rules, curr_rule):
- return "%s_%s_%s" % (
- depth, curr_rule.__str__(), curr_pos
- )
- jitdriver = JitDriver(
- greens=['depth', 'curr_pos', 'iterations', 'surface', 'context',
- 'rules', 'curr_rule',
- ],
- reds=['state', 'exec_stack'],
- get_printable_location=get_location)
- @purefunction
- def get_rule(rules, symbol):
- return rules[symbol]
- @purefunction
- def is_in_rules(rules, symbol):
- return symbol in rules
- def mainloop(iterations, start, rules):
- surface = cairo_image_surface_create(0, WIDTH, HEIGHT)
- context = cairo_create(surface)
- cairo_set_source_rgb(context, 0.0, 0.0, 0.0)
- cairo_paint(context)
- cairo_move_to(context, WIDTH / 2, HEIGHT / 2)
- state = DrawingState()
- state.pos = (WIDTH / 2, HEIGHT / 2)
- exec_stack = []
- depth = 0
- curr_rule = get_rule(rules, start)
- curr_pos = 0
- while True:
- jitdriver.jit_merge_point(
- depth=depth, curr_pos=curr_pos, iterations=iterations,
- surface=surface, context=context,
- rules=rules, exec_stack=exec_stack,
- curr_rule=curr_rule,
- state=state)
- if curr_pos >= len(curr_rule.tokens):
- if len(exec_stack) == 0:
- stop = True
- break
- else:
- curr_rule, curr_pos = exec_stack.pop()
- curr_pos += 1
- depth -= 1
- jitdriver.can_enter_jit(
- depth=depth, curr_pos=curr_pos, iterations=iterations,
- surface=surface, context=context,
- rules=rules, exec_stack=exec_stack,
- curr_rule=curr_rule,
- state=state)
- continue
- symbol = curr_rule.tokens[curr_pos]
- if is_in_rules(rules, symbol) and depth < iterations:
- depth += 1
- exec_stack.append((curr_rule, curr_pos))
- curr_rule, curr_pos = get_rule(rules, symbol), -1
- # curr_pos will be incremented _always_
- elif symbol == "+":
- state.angle += math.pi / 2.0
- elif symbol == "-":
- state.angle -= math.pi / 2.0
- elif symbol == "F":
- state.pos = (state.pos[0] + math.cos(state.angle) * state.step,
- state.pos[1] + math.sin(state.angle) * state.step)
- cairo_line_to(context, state.pos[0], state.pos[1])
- else:
- pass
- curr_pos += 1
- cairo_set_source_rgb(context, 1.0, 1.0, 1.0)
- cairo_stroke(context)
- cairo_surface_write_to_png(surface, "out.png")
- cairo_surface_destroy(surface)
- cairo_destroy(context)
- def parse(program):
- iterations = 0
- start = ""
- rules = {}
- for line in program.split("\n"):
- l = line.split(":")
- if len(l) == 2:
- lhs, rhs = l[0].strip(" "), l[1].strip(" ")
- if lhs == "iterations":
- iterations = int(rhs)
- elif lhs == "start":
- start = rhs
- elif lhs != "":
- r = Rule(lhs, rhs)
- rules[lhs] = r
- return iterations, start, rules
- def run(fp):
- program_contents = ""
- while True:
- read = os.read(fp, 4096)
- if len(read) == 0:
- break
- program_contents += read
- os.close(fp)
- iterations, start, rules = parse(program_contents)
- mainloop(iterations, start, rules)
- def entry_point(argv):
- try:
- filename = argv[1]
- except IndexError:
- print "You must supply a filename"
- return 1
- run(os.open(filename, os.O_RDONLY, 0777))
- return 0
- def target(*args):
- return entry_point, None
- def jitpolicy(driver):
- from pypy.jit.codewriter.policy import JitPolicy
- return JitPolicy()
- if __name__ == "__main__":
- entry_point(sys.argv)
Add Comment
Please, Sign In to add comment