Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

*.un~
77 changes: 44 additions & 33 deletions mpython.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,67 @@
#!/usr/bin/python
#!/usr/bin/env python

from ast import *
import ast
import sys


def name(x, ctx):
return Name(id = x, ctx = ctx, lineno = 0, col_offset = 0)
return ast.Name(id=x, ctx=ctx, lineno=0, col_offset=0)


def call(f, *args):
f = name(f, Load())
return Call(func = f, args = list(args), lineno = 0,
col_offset = 0, keywords = [], vararg = None)
f = name(f, ast.Load())
return ast.Call(func=f, args=list(args), lineno=0,
col_offset=0, keywords=[], vararg=None)


def func(args, body):
return Lambda(args = arguments(args = args, defaults = []),
body = body, vararg = None, lineno = 0, col_offset = 0)
return ast.Lambda(args=ast.arguments(args=args, defaults=[]),
body=body, vararg=None, lineno=0, col_offset=0)


unit = ast.Tuple(elts=[], lineno=0, col_offset=0, ctx=ast.Load())

unit = Tuple(elts = [], lineno=0, col_offset = 0, ctx = Load())

def transform(elt, generators):
elt = call("__singleton__", elt)

for generator in generators[-1::-1]:
for i in generator.ifs[-1::-1]:
elt = call("__concatMap__",
func([name('_', Param())], elt),
IfExp(i,
call('__singleton__', unit),
call('__fail__'), lineno=0, col_offset=0))

elt = call("__concatMap__",
func([name(generator.target.id, Param())], elt),
generator.iter)
return elt

class RewriteComp(NodeTransformer):
def visit_ListComp(self, node):
return transform(RewriteComp().visit(node.elt),
[RewriteComp().visit(generator) for generator in node.generators])
elt = call("__singleton__", elt)

for generator in reversed(generators):
for i in reversed(generator.ifs):
elt = call("__concatMap__",
func([name('_', ast.Param())], elt),
ast.IfExp(i,
call('__singleton__', unit),
call('__fail__'), lineno=0, col_offset=0))

elt = call("__concatMap__",
func([name(generator.target.id, ast.Param())], elt),
generator.iter)
return elt


class RewriteComp(ast.NodeTransformer):
def visit_ListComp(self, node):
return transform(RewriteComp().visit(node.elt),
[RewriteComp().visit(generator)
for generator in node.generators])


def __concatMap__(f, x):
return [z for y in x for z in f(y)]
return [z for y in x for z in f(y)]


def __singleton__(x):
return [x]
return [x]


def __fail__():
return []
return []


source = open(sys.argv[1]).read()
e = compile(source, "<string>", "exec", PyCF_ONLY_AST)
e = compile(source, "<string>", "exec", ast.PyCF_ONLY_AST)
e = RewriteComp().visit(e)
f = compile(e, sys.argv[1], "exec")
print f
exec f
print "Done"
print "Done"
30 changes: 18 additions & 12 deletions test1.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
# Some simple regression tests

a = [(x, y, z) for x in [0, 1, 2]
for y in [0, 1, 2]
for z in [0, 1, 2]]
a = [
(x, y, z)
for x in [0, 1, 2]
for y in [0, 1, 2]
for z in [0, 1, 2]]

print len(a)

b = [(x, y) for x in [0,1]
for y in [0,1]
if x+y < 2]
b = [
(x, y)
for x in [0, 1]
for y in [0, 1]
if x+y < 2]

print b

c = [(x, y, z) for x in range(1, 10)
for y in range(1, 10)
if x < y
for z in range(1, 10)
if x*x+y*y == z*z]
c = [
(x, y, z)
for x in range(1, 10)
for y in range(1, 10)
if x < y
for z in range(1, 10)
if x*x+y*y == z*z]

print c
print c
33 changes: 21 additions & 12 deletions test2.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import math


def __concatMap__(k, m):
return lambda c:m(lambda a:k(a)(c))
return lambda c: m(lambda a: k(a)(c))


def __singleton__(x):
return lambda f:f(x)
return lambda f: f(x)


def callCC(f):
return lambda c:f(lambda a:lambda _:c(a))(c)
return lambda c: f(lambda a: lambda _: c(a))(c)


def __fail__():
raise "Failure is not an option for continuations"
raise "Failure is not an option for continuations"


def ret(x):
return __singleton__(x)
return __singleton__(x)


def id(x):
return x
return x


def solve(a, b, c):
return callCC(lambda throw: [((-b-d)/(2*a), (-b+d)/(2*a))
for a0 in (ret(a) if a!=0 else throw("Not quadratic"))
for d2 in ret(b*b-4*a*c)
for d in (ret(math.sqrt(d2)) if d2>=0 else throw("No roots"))
])
return callCC(
lambda throw: [
((-b-d)/(2*a), (-b+d)/(2*a))
for a0 in (ret(a) if a != 0 else throw("Not quadratic"))
for d2 in ret(b*b-4*a*c)
for d in (ret(math.sqrt(d2)) if d2 >= 0 else throw("No roots"))
])

print solve(1, 0, -9)(id)
print solve(1, 1, 9)(id)
print solve(0, 1, 9)(id)
print solve(0, 1, 9)(id)
Loading