def char_on_predicate(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'))
  if not isinstance(test, il.PyFunction):
    raise DaoCompileTypeError(test)
  return il.Begin((
    il.AssignFromList(text, pos, il.parse_state),
    il.If(il.Ge(pos,il.Len(text)), 
      il.failcont(il.FALSE),
      il.If(il.Call(test, il.GetItem(text, pos)),
        il.begin(
          il.SetParseState(il.Tuple(text, il.add(pos, il.Integer(1)))),
          il.append_failcont(compiler, 
                             il.SetParseState(il.Tuple(text, pos))),
          cont(il.GetItem(text, pos))),
        il.failcont(il.FALSE)))))