def once(compiler, cont, exp): v = compiler.new_var(il.ConstLocalVar('v')) fc = compiler.new_var(il.ConstLocalVar('fc')) return il.begin( il.Assign(fc, il.failcont), exp.cps(compiler, il.clamda(v, il.SetFailCont(fc), cont(v))))
def unify_head_item2(compiler, cont, arg, head_item): # for call with rules variable. arg = arg.interlang() if not isinstance(head_item, Var): # arg should be Var if isinstance(head_item, Cons): v = compiler.new_var(il.ConstLocalVar('v')) return do_unify_head_item2(il.ConsHead(arg), head_item.head, compiler, il.clamda(v, do_unify_head_item2(il.ConsTail(arg), head_item.tail, compiler, cont))) else: head_item = head_item.interlang() arg1 = compiler.new_var(il.ConstLocalVar('arg')) return il.begin( il.Assign(arg1, il.Deref(arg)), il.If(il.IsLogicVar(arg1), il.begin(il.SetBinding(arg1, head_item), il.append_failcont(compiler, il.DelBinding(arg1)), cont(il.TRUE)), il.If(il.Eq(arg1, head_item), cont(TRUE), il.failcont(TRUE)))) else: if not isinstance(head_item, LogicVar): return il.begin( il.Assign(head_item.interlang(), arg), cont(il.TRUE)) else: raise CompileTypeError
def between(compiler, cont, lower, upper, mid): lower1 = compiler.new_var(il.ConstLocalVar('lower')) upper1 = compiler.new_var(il.ConstLocalVar('upper')) mid1 = compiler.new_var(il.ConstLocalVar('mid')) fc = compiler.new_var(il.ConstLocalVar('fc')) i = compiler.new_var(il.Var('i')) v = compiler.new_var(il.ConstLocalVar('v')) return lower.cps(compiler, il.clamda(lower1, upper.cps(compiler, il.clamda(upper1, mid.cps(compiler, il.clamda(mid1, il.If(il.IsLogicVar(mid1), il.begin( il.Assign(i, lower1), il.Assign(fc, il.failcont), il.SetFailCont(il.clamda(v, il.If(il.Eq(i, upper1), il.Begin(( il.Assign(il.failcont, fc), fc(il.FALSE))), il.Begin(( il.AddAssign(i, il.Integer(1)), il.SetBinding(mid1, i), cont(il.TRUE)))))), il.SetBinding(mid1, lower1), cont(il.TRUE)), il.If(il.Cle(lower1, mid1, upper1), cont(il.TRUE), il.failcont(il.FALSE))))) ))))
def repeat(compiler, cont): v = compiler.new_var(il.ConstLocalVar('v')) function = compiler.new_var(il.ConstLocalVar('function')) return il.begin(il.cfunction(function, v, cont(v)), il.PrintLn(il.String('repeat')), il.SetFailCont(function), function(NONE))
def cps_convert_unify(x, y, compiler, cont): try: y.cps_convert_unify except: x = x.interlang() y = y.interlang() x1 = compiler.new_var(il.ConstLocalVar(x.name)) return il.begin( il.Assign(x1, il.Deref(x)), #for LogicVar, could be optimized when generate code. il.If(il.IsLogicVar(x1), il.begin(il.SetBinding(x1, y), il.append_failcont(compiler, il.DelBinding(x1)), cont(il.TRUE)), il.If(il.Eq(x1, y), cont(il.TRUE), il.failcont(il.TRUE)))) x = x.interlang() y = y.interlang() x1 = compiler.new_var(il.ConstLocalVar(x.name)) y1 = compiler.new_var(il.ConstLocalVar(y.name)) return il.begin( il.Assign(x1, il.Deref(x)), #for LogicVar, could be optimized when generate code. il.Assign(y1, il.Deref(y)), il.If(il.IsLogicVar(x1), il.begin(il.SetBinding(x1, y1), il.append_failcont(compiler, il.DelBinding(x1)), cont(il.TRUE)), il.begin( il.If(il.IsLogicVar(y1), il.begin(il.SetBinding(y1, x1), il.append_failcont(compiler, il.DelBinding(y1)), cont(il.TRUE)), il.If(il.Eq(x1, y1), cont(il.TRUE), il.failcont(il.TRUE))))))
def eval_unify(compiler, cont, x, y): x1 = compiler.new_var(il.ConstLocalVar('x')) y1 = compiler.new_var(il.ConstLocalVar('y')) return x.cps( compiler, il.clamda( x1, y.cps( compiler, il.clamda( y1, il.If( il.IsLogicVar(x1), il.begin( il.SetBinding(x1, y1), il.append_failcont(compiler, il.DelBinding(x1)), cont(il.TRUE)), il.If( il.IsLogicVar(y1), il.begin( il.SetBinding(y1, x1), il.append_failcont(compiler, il.DelBinding(y1)), cont(il.TRUE)), il.If(il.Eq(x1, y1), cont(il.TRUE), il.failcont(il.TRUE))))))))
def follow(compiler, cont, item): parse_state = compiler.new_var(il.ConstLocalVar('parse_state')) v = compiler.new_var(il.ConstLocalVar('v')) return il.begin( il.Assign(parse_state, il.parse_state), item.cps(compiler, il.clamda(v, il.SetParseState(parse_state), cont(v))))
def any2(compiler, cont, item, template, result): template = template.interlang() result = result.interlang() any_cont = compiler.new_var(il.ConstLocalVar('any_cont')) fc = compiler.new_var(il.ConstLocalVar('old_fail_cont')) v = compiler.new_var(il.ConstLocalVar('v')) v2 = compiler.new_var(il.ConstLocalVar('v')) v3 = compiler.new_var(il.ConstLocalVar('v')) return il.Begin( (il.Assign(result, il.empty_list), il.cfunction( any_cont, v, il.Assign(fc, il.failcont), il.SetFailCont( il.clamda( v, il.SetFailCont( il.clamda( v3, il.if2(result, il.DelListItem(result, il.Integer(-1))), fc(v3))), cont(v))), item.cps( compiler, il.clamda(v2, il.ListAppend(result, il.GetValue(template)), any_cont(v2))))(il.NONE)))
def compile_to_python(exp, env, done=None): '''assemble steps from dao expression to python code''' original_exp = exp compiler = Compiler() if done is None: done = il.Done(compiler.new_var(il.ConstLocalVar('v'))) compiler.exit_block_cont_map = {} compiler.continue_block_cont_map = {} compiler.protect_cont = done if env is None: env = Environment() exp = element(exp) exp = exp.alpha(env, compiler) exp = exp.cps(compiler, done) exp.analyse(compiler) env = Environment() exp = exp.optimize(env, compiler) #exp = exp.tail_recursive_convert() function = compiler.new_var(il.ConstLocalVar('compiled_dao_function')) exp = il.Function(function, (), exp) exp = il.begin(*exp.pythonize(env, compiler)[0]) if isinstance(exp, il.Begin): exp = exp.statements[0] exp.body = exp.body.replace_return_with_yield() compiler = Compiler() result = exp.to_code(compiler) return prelude + result
def string_on_predicate1(compiler, cont, test): '''return current char and step if @test succeed, where @test: a python function with one argument, which tests on one char and return True or False @test must be registered with register_function''' test = test.interlang() text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) length = compiler.new_var(il.ConstLocalVar('length')) p = compiler.new_var(il.LocalVar('p')) if not isinstance(test, il.PyFunction): raise DaoCompileTypeError(test) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), il.Assign(length, il.Len(text)), il.If(il.Ge(pos, length), il.failcont(il.FALSE), il.If(il.Call(test, il.GetItem(text, pos)), il.begin( il.Assign(p, il.add(pos, il.Integer(1))), il.While(il.And(il.Lt(p, length), il.Call(test, il.GetItem(text, p))), il.AddAssign(p, il.Integer(1))), il.SetParseState(il.Tuple(text, p)), il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos))), cont(il.GetItem(text, il.Slice2(pos, p)))), il.failcont(il.FALSE)))))
def unify_macro_head_item2(compiler, cont, arg, head_item): if isinstance(head_item, Var): if not isinstance(head_item, LogicVar): return il.begin( il.Assign(head_item.interlang(), arg), cont(il.TRUE)) else: v = compiler.new_var(il.ConstLocalVar('v')) head_item = head_item.interlang() arg1 = compiler.new_var(il.ConstLocalVar('arg')) head1 = compiler.new_var(il.ConstLocalVar('head')) return il.begin( il.Assign(arg1, il.Deref(arg)), #for LogicVar, could be optimized when generate code. il.Assign(head1, il.Deref(head_item)), il.If(il.IsLogicVar(arg1), il.begin(il.SetBinding(arg1, head1), il.append_failcont(compiler, il.DelBinding(arg1)), cont(il.TRUE)), il.begin( il.If(il.IsLogicVar(head1), il.begin(il.SetBinding(head1, arg1), il.append_failcont(compiler, il.DelBinding(head1)), cont(il.TRUE)), il.If(il.Eq(arg1, head1), cont(il.TRUE), il.failcont(il.FALSE)))))) else: arg1 = compiler.new_var(il.ConstLocalVar('arg')) return il.begin( il.Assign(arg1, il.Deref(arg)), il.If(il.IsLogicVar(arg1), il.begin(il.SetBinding(arg1, head_item), il.append_failcont(compiler, il.DelBinding(arg1)), cont(il.TRUE)), il.If(il.Eq(arg1, head_item), cont(TRUE), il.failcont(TRUE))))
def left(compiler, cont, length=NONE): text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), cont(il.GetItem(text, il.If(il.IsNot(length, NONE), il.Slice2(pos, il.add(pos,length)), il.Slice2(pos, NONE))))))
def subsequence(compiler, cont, start, end): text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) start = il.Integer(start.item) end = il.Integer(end.item) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), cont(il.GetItem(text, il.Slice2(start, end)))))
def any1(compiler, cont, item): any_cont = compiler.new_var(il.ConstLocalVar('any_cont')) fc = compiler.new_var(il.ConstLocalVar('old_fail_cont')) v = compiler.new_var(il.ConstLocalVar('v')) return il.cfunction( any_cont, v, il.Assign(fc, il.failcont), il.SetFailCont(il.clamda(v, il.SetFailCont(fc), cont(v))), item.cps(compiler, any_cont))(il.TRUE)
def first_(compiler, cont, clause1, clause2): v = compiler.new_var(il.ConstLocalVar('v')) fc = compiler.new_var(il.ConstLocalVar('fc')) first_cont = il.clamda(v, il.SetFailCont(fc), cont(v)) return il.begin( il.Assign(fc, il.failcont), il.append_failcont(compiler, clause2.cps(compiler, first_cont)), clause1.cps(compiler, first_cont))
def integer(compiler, cont, arg): '''integer''' text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) p = compiler.new_var(il.LocalVar('p')) length = compiler.new_var(il.ConstLocalVar('length')) if isinstance(arg, Var): arg = arg.interlang() x = compiler.new_var(il.ConstLocalVar('x')) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), il.Assign(length, il.Len(text)), il.If(il.Ge(pos, length), il.failcont(il.FALSE), il.If(il.Not(il.Cle(il.String('0'), il.GetItem(text, pos), il.String('9'))), il.failcont(il.FALSE), il.Begin(( il.Assign(p, il.add(pos, il.Integer(1))), il.while_(il.And(il.Lt(p, length), il.Cle(il.String('0'),il.GetItem(text, p),il.String('9'))), il.AddAssign(p, il.Integer(1))), il.Assign(x, il.Deref(arg)), il.If(il.IsLogicVar(x), il.begin(il.SetParseState(il.Tuple(text, p)), il.SetBinding(x, il.GetItem(text, il.Slice2(pos, p))), il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos)), il.DelBinding(x)), cont(il.GetItem(text, pos))), il.If(il.Isinstance(x, il.String('str')), il.If(il.Eq(x, il.GetItem(text, il.Slice2(pos, p))), il.begin(il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos))), il.SetParseState(il.Tuple(text, p)), cont(il.GetItem(text, pos))), il.failcont(il.NONE)), il.RaiseTypeError(x))))))))) elif isinstance(arg, il.String): return il.Begin(( il.AssignFromList(text, pos, il.parse_state), il.Assign(length, il.Len(text)), il.If(il.Ge(pos, length), il.failcont(il.FALSE), il.If(il.Not(il.Cle(il.String('0'), il.GetItem(text, pos), il.String('9'))), il.failcont(il.FALSE), il.Begin(( il.Assign(p, il.add(pos, il.Integer(1))), il.while_(il.And(il.Lt(p, length), il.Cle(il.String('0'),il.GetItem(text, p),il.String('9'))), il.AddAssign(p, il.Integer(1))), il.If(il.Eq(arg, il.GetItem(text, il.Slice2(pos, p))), il.begin(il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos))), il.SetParseState(il.Tuple(text, p)), cont(arg)), il.failcont(il.NONE)))))))) else: raise CompileTypeError
def some1(compiler, cont, item): some_cont = compiler.new_var(il.ConstLocalVar('some_cont')) fc = compiler.new_var(il.ConstLocalVar('old_fail_cont')) v = compiler.new_var(il.ConstLocalVar('v')) some_cont = il.cfunction( some_cont, v, il.Assign(fc, il.failcont), il.SetFailCont(il.clamda(v, il.SetFailCont(fc), cont(v))), item.cps(compiler, some_cont)) return item.cps(compiler, some_cont)
def goto(compiler, cont, position): text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) position = il.Integer(position.item) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos))), il.SetParseState(il.Tuple(text, position)), cont(il.GetItem(text, position))))
def cps_call(self, compiler, cont, args): function = self.interlang() k = compiler.new_var(il.ConstLocalVar('cont')) v = compiler.new_var(il.ConstLocalVar('v')) #macro_args = tuple(il.Lamda((), arg.cps(compiler, il.clamda(v, v))) #for arg in args) macro_args = tuple(il.Lamda((k,), arg.cps(compiler, k)) for arg in args) return self.cps(compiler, il.clamda(function, il.Apply(function, (cont,)+macro_args)))
def skip(compiler, cont, n=il.Integer(1)): # return element after skip text = compiler.new_var(il.ConstLocalVar('text')) pos = compiler.new_var(il.ConstLocalVar('pos')) return il.Begin(( il.AssignFromList(text, pos, il.parse_state), il.append_failcont(compiler, il.SetParseState(il.Tuple(text, pos))), il.SetParseState(il.Tuple(text, il.add(pos, n))), cont(il.GetItem(text, il.add(pos, n)))))
def catch(compiler, cont, tag, *form): v = compiler.new_var(il.ConstLocalVar('v')) v2 = compiler.new_var(il.ConstLocalVar('v')) k = compiler.new_var(il.LocalVar('cont')) return tag.cps( compiler, il.clamda(v, il.Assign(k, il.clamda(v2, cont(v2))), il.PushCatchCont(v, k), begin(*form).cps(compiler, cont)))
def callcc(compiler, cont, function): body = function.body.subst( {function.params[0]: LamdaVar(function.params[0].name)}) k = compiler.new_var(il.ConstLocalVar('cont')) params = tuple(x.interlang() for x in function.params) function1 = il.Lamda((k, ) + params, body.cps(compiler, k)) k1 = compiler.new_var(il.ConstLocalVar('cont')) v = compiler.new_var(il.ConstLocalVar('v')) return function1(cont, il.Lamda((k1, v), cont(v)))
def greedy_any1(compiler, cont, item): v = compiler.new_var(il.ConstLocalVar('v')) fc = compiler.new_var(il.ConstLocalVar('old_failcont')) greedy_any_fcont = compiler.new_var(il.ConstLocalVar('greedy_any_fcont')) greedy_any_cont = compiler.new_var(il.ConstLocalVar('greedy_any_cont')) return il.begin( il.Assign(fc, il.failcont), il.cfunction(greedy_any_fcont, v, il.SetFailCont(fc), cont(il.TRUE)), il.cfunction(greedy_any_cont, v, il.SetFailCont(greedy_any_fcont), item.cps(compiler, greedy_any_cont))(il.TRUE))
def cps_call(self, compiler, cont, args): #function = compiler.new_var(il.ConstLocalVar('function')) function = self.interlang() vars = tuple(compiler.new_var(il.ConstLocalVar('a'+repr(i))) for i in range(len(args))) body = il.Apply(function, (cont,)+vars) for var, item in reversed(zip(vars, args)): body = item.cps(compiler, il.clamda(var, body)) v = compiler.new_var(il.ConstLocalVar('v')) return self.cps(compiler, il.clamda(function,body))
def parse(compiler, cont, predicate, parse_state): old_parse_state = compiler.new_var(il.ConstLocalVar('old_parse_state')) v = compiler.new_var(il.ConstLocalVar('v')) return il.begin(il.Assign(old_parse_state, il.parse_state), il.SetParseState(parse_state), il.append_failcont(compiler, il.SetParseState(old_parse_state)), predicate.cps(compiler, il.clamda(v, il.Assign(il.parse_state, old_parse_state), cont(v))))
def findall_1(compiler, cont, goal): v = compiler.new_var(il.ConstLocalVar('v')) v2 = compiler.new_var(il.ConstLocalVar('v')) fc = compiler.new_var(il.ConstLocalVar('old_failcont')) return il.begin( il.Assign(fc, il.failcont), il.SetFailCont(il.clamda(v2, il.SetFailCont(fc), cont(v2))), goal.cps(compiler, il.Clamda(v, il.failcont(v))) )
def lazy_any1(compiler, cont, item): fc = compiler.new_var(il.ConstLocalVar('fc')) lazy_any_cont = compiler.new_var(il.ConstLocalVar('lazy_any_cont')) lazy_any_fcont = compiler.new_var(il.ConstLocalVar('lazy_any_fcont')) v = compiler.new_var(il.ConstLocalVar('v')) return il.begin( il.Assign(fc, il.failcont), il.cfunction(lazy_any_fcont, v, il.SetFailCont(fc), item.cps(compiler, lazy_any_cont)), il.cfunction(lazy_any_cont, v, il.SetFailCont(lazy_any_fcont), cont(il.TRUE))(il.TRUE))
def parse_sequence(compiler, cont, predicate, sequence): old_parse_state = compiler.new_var(il.ConstLocalVar('old_parse_state')) v = compiler.new_var(il.ConstLocalVar('v')) sequence = sequence.interlang() return il.begin(il.Assign(old_parse_state, il.parse_state), il.SetParseState(il.Tuple(sequence, il.Integer(0))), il.append_failcont(compiler, il.SetParseState(old_parse_state)), predicate.cps(compiler, il.clamda(v, il.SetParseState(old_parse_state), cont(v))))
def throw(compiler, cont, tag, form): v = compiler.new_var(il.ConstLocalVar('v')) v2 = compiler.new_var(il.ConstLocalVar('v')) return tag.cps( compiler, il.clamda( v, form.cps( compiler, il.clamda(v2, compiler.protect_cont(NONE), il.FindCatchCont(v)(v2)))))
def cps(self, compiler, cont): # use cfunction, continue_block means recursive call. # tail recursive cfunction can be used to transform to while 1/break/continue. v = compiler.new_var(il.ConstLocalVar('v')) v1 = compiler.new_var(il.ConstLocalVar('v')) v2 = compiler.new_var(il.ConstLocalVar('v')) block_fun = compiler.new_var( il.ConstLocalVar('block_' + self.label.name)) compiler.exit_block_cont_map[self.label.name] = il.clamda(v1, cont(v1)) compiler.continue_block_cont_map[self.label.name] = il.clamda( v2, block_fun(v2)) return il.cfunction(block_fun, v, self.body.cps(compiler, cont))(il.NONE)