def test_mc_routine_5(): from xotl.ql import qst from xotl.ql.translation._monads import _mc this = list(range(10, 15)) + list(range(5, 10)) genexpr = qst.parse('(x for x in this if 7 < x < 13)') result = _mc(genexpr) # In this test, we won't use our implementation of the monadic functions # but translate them directly to Python. res = eval(compile(result, '', 'eval'), {'this': this, 'Join': lambda x: [i for b in x for i in b], 'Map': lambda f: lambda x: [f(i) for i in x], 'Empty': lambda: [], 'Unit': lambda x: [x]}) assert res == [10, 11, 12, 8, 9] genexpr = qst.parse('sorted(x for x in this if 7 < x < 13)') result = _mc(genexpr) # In this test, we won't use our implementation of the monadic functions # but translate them directly to Python. res = eval(compile(result, '', 'eval'), {'this': this, 'Join': lambda x: [i for b in x for i in b], 'Map': lambda f: lambda x: [f(i) for i in x], 'Empty': lambda: [], 'Unit': lambda x: [x]}) assert res == [8, 9, 10, 11, 12]
def __new__(cls, expr, alt): from xotl.ql import qst if not isinstance(alt, tuple): alt = (alt, ) res = object.__new__(cls) res.alts = [qst.parse(a) for a in alt] res.alts.insert(0, qst.parse(expr)) return res
def test_mc_routine_2(): from xotl.ql import qst from xotl.ql.revenge.qst import Name, Load, Lambda from xotl.ql.translation._monads import _mc, _make_arguments genexpr = qst.parse('(x for x in this)') # MC [x | x <- this] = Map(lambda x: x)(this) expected = Call( Call( Name('Map', Load()), Lambda(_make_arguments('x'), Name('x', Load())) ), Name('this', Load()) ) result = _mc(genexpr) try: assert result.body == expected except: print(result) print(expected) raise this = Cons('I should be in the result', ['And me too']) res = eval(compile(result, '', 'eval'), {'this': this, 'Join': Join, 'Map': Map, 'Empty': Empty, 'Unit': Unit})().aslist() assert res == ['I should be in the result', 'And me too']
def test_conditional_a_la_pypy(): from xotl.ql import qst # >>> dis.dis(compile('x and a or y', '', 'eval')) # 1 0 LOAD_NAME 0 (x) # 3 JUMP_IF_FALSE_OR_POP 9 # 6 LOAD_NAME 1 (a) # >> 9 JUMP_IF_TRUE_OR_POP 15 # 12 LOAD_NAME 2 (y) # >> 15 RETURN_VALUE import types from xotl.ql.revenge import Uncompyled from xotl.ql.revenge.scanners import InstructionSetBuilder, label builder = InstructionSetBuilder() with builder() as Instruction: Instruction(opname='LOAD_NAME', arg=0, argval='x', starts_line=1) Instruction(opname='JUMP_IF_FALSE_OR_POP', arg=label('else')) Instruction(opname='LOAD_NAME', arg=1, argval='a') Instruction(label='else', opname='JUMP_IF_TRUE_OR_POP', arg=label('out')) Instruction(opname='LOAD_NAME', arg=2, argval='y') Instruction(label='out', opname='RETURN_VALUE') code = builder.code code = types.CodeType(0, 0, 0, 3, 0, code, (), ('x', 'a', 'y'), (), '', '<module>', 1, b'') u = Uncompyled(code) assert u.safe_ast expected = qst.parse('x and a or y') assert u.qst == expected
def test_mc_routine_4(): from xotl.ql import qst from xotl.ql.revenge.qst import Name, Load, Lambda, Compare, In, Str from xotl.ql.translation._monads import _mc, _make_arguments genexpr = qst.parse('all("s" in x for x in this)') # MC all(["s" in x | x <- this]) = all(Map(lambda x: 's' in x)(this)) expected = Call( Name('all', Load()), Call( Call( Name('Map', Load()), Lambda( _make_arguments('x'), Compare( Str('s'), [In()], [Name('x', Load())] ) ) ), Name('this', Load()) ) ) result = _mc(genexpr) try: assert result.body == expected except: print(result.body) print(expected) assert str(result) == str(expected) raise # Map returns a Cons and Cons iters yielding x, xs not the items. To # compile this we must make all a foldr, that easily defined by # 'Foldr(operator.and, True)'. All the same 'any' is 'Foldr(operator.or_, # False)', 'sum' is 'Foldr(operator.add, 0)', etc... this = Cons('Yes!!', ['No!!']) res = eval(compile(result, '', 'eval'), {'this': this, 'Join': Join, 'all': Foldr(operator.and_, True), 'Map': Map, 'Empty': Empty, 'Unit': Unit}) assert res is False this = Empty() res = eval(compile(result, '', 'eval'), {'this': this, 'Join': Join, 'all': Foldr(operator.and_, True), 'Map': Map, 'Empty': Empty, 'Unit': Unit}) assert res is True this = Cons('Yes!!!', Empty()) res = eval(compile(result, '', 'eval'), {'this': this, 'Join': Join, 'all': Foldr(operator.and_, True), 'Map': Map, 'Empty': Empty, 'Unit': Unit}) assert res is True
def _do_test(expressions): codes = [ ( qst.parse(expr), expr, qst.pyast.parse(expr, '<test>', 'eval') ) for expr, _expected in expressions ] for qst_, expr, ast in codes: assert qst_ == ast
def test_mc_routine_1(): from xotl.ql import qst from xotl.ql.revenge.qst import Name, IfExp, Load, Lambda from xotl.ql.translation.monads import ( translate, _make_arguments, Join, Map, Empty, Unit, Cons ) genexpr = qst.parse('(x for x in this if predicate(x))') # MC [x | x <- this, predicate(x)] # = Join(Map(lambda x: Unit(x) if predicate(x) else Empty())(this)) expected = Call( Name('join', Load()), Call( Call( Name('map', Load()), Lambda( _make_arguments('x'), IfExp( Call(Name('predicate', Load()), Name('x', Load())), Call(Name('unit', Load()), Name('x', Load())), Call(Name('empty', Load())) ) ) ), Name('this', Load()) ) ) result = translate(genexpr, map='map', join='join', zero='empty', unit='unit') assert result.body == expected predicate = lambda x: 's' in x this = Cons('I should be in the result', ['But I cannot be']) res = eval(compile(result, '', 'eval'), {'this': this, 'predicate': predicate, 'join': Join, 'map': Map, 'empty': Empty, 'unit': Unit}) assert res().list() == ['I should be in the result']