content: #!/usr/bin/env python
  import sys
  from types import FunctionType
  from functools import reduce, partial
  from itertools import chain
  from operator import concat, add
  from collections import Iterator, Iterable, Sequence, MutableSequence
  from io import StringIO
  
  from pyrsistent import pmap
  
  from mochi.parser import lex
  from .utils import issequence, issequence_except_str, is_tuple_or_list
  from .constants import *
  from .exceptions import UnquoteSplicingError, DuplicatedDefError, ReadError
  from .global_env import global_env, global_mod
  from .translation import binding_name_set_stack, translator, Keyword, parse
  
  
  def builtin(func):
      global_env[func.__name__] = func
      return func
  
  
  def builtin_rename(new_name):
      def _builtin(func):
          global_env[new_name] = func
          return func
  
      return _builtin
  
  
  #@builtin_rename('uniq')
  #@builtin_rename('gensym')
  
  
  @builtin
  def flip(func):
      return lambda arg0, arg1, *rest: func(arg1, arg0, *rest)
  
  
  @builtin
  def bind(next_func, input):
      if input is None:
          return None
      return next_func(input)
  
  
  @builtin
  def mapchain(func, iterable):
      return reduce(chain, map(func, iterable))
  
  
  @builtin
  def mapcat(func, iterable):
      return reduce(concat, map(func, iterable))
  
  
  @builtin
  def mapadd(func, iterable):
      return reduce(add, map(func, iterable))
  
  
  @builtin_rename('on_err')
  def handle(onerror, func, *args, **kwargs):
      try:
          return func(*args, **kwargs)
      except Exception as e:
          return onerror(e)
  
  
  @builtin
  def protect(during_func, after_func):
      try:
          return during_func()
      finally:
          after_func()
  
  
  @builtin
  def err(message, exc_type=Exception):
      raise exc_type(message)
  
  
  @builtin
  def details(exc):
      return str(exc)
  
  
  @builtin
  def ignore(func, default, *args, **kwargs):
      try:
          return func(*args, **kwargs)
      except:
          return default
  
  
  @builtin
  def silent(func, *args, **kwargs):
      return ignore(func, None, *args, **kwargs)
  
  
  @builtin
  def gen_with(context, func):
      with context:
          retval = func(context)
          if isinstance(retval, Iterable):
              # yield from retval
              for value in retval:
                  yield value
          else:
              yield retval
  
  
  #@builtin_rename('with')
  #def _with(context, func):
  #    with context:
  #        return func(context)
  
  
  @builtin
  def gen(func, iterable):
      while True:
          yield func(next(iterable))
  
  
  @builtin
  def each_with_index(iterable, func):
      for index, value in enumerate(iterable):
          func(index, value)
  
  
  @builtin
  def dorun(iterable):
      retval = None
      for value in iterable:
          retval = value
      return retval
  
  
  @builtin
  def require_py_module(*target_symbols):
      return _require_py_module(target_symbols)
  
  
  @builtin
  def _require_py_module(target_symbols):
      binding_name_set = binding_name_set_stack[0]
      for target_symbol in target_symbols:
          target_obj = None
          target = target_symbol.name.split('.')
          if len(target) > 1:
              package = target[0]
              module = '.'.join(target[:-1])
              target_name = target[-1]
              if target_name in binding_name_set:
                  continue
              target_obj = getattr(__import__(module, fromlist=[package]), target_name)
          elif len(target) == 1:
              target_name = target[0]
              if target_name == 'builtins' or target_name in binding_name_set:
                  continue
              target_obj = __import__(target_name)
          binding_name_set.add_binding_name(target_name, "<string>")  # TODO
          global_env[target_name] = target_obj
      return True
  
  
  @builtin
  def cons(head, tail):
      if isinstance(tail, Iterator):
          return chain((head,), tail)
      if isinstance(tail, cell):
          return cell(head, tail)
      if tail is None:
          return cell(head, None)
      return (head,) + tail
  
  
  @builtin
  def conj(seq, item):
      assert issequence_except_str(seq)
      return seq + type(seq)((item,))
  
  
  @builtin
  @builtin_rename('first')
  def car(seq):
      return seq[0]
  
  
  @builtin
  @builtin_rename('rest')
  def cdr(seq):
      return seq[1:]
  
  
  @builtin
  def last(seq):
      return seq[-1]
  
  
  @builtin
  def chunks(l, n):
      for i in range(0, len(l), n):
          yield l[i:i + n]
  
  
  def symbolp(obj):
      return type(obj) is Symbol
  
  
  def symbol_to_string(sym):
      return sym.name
  
  
  def string_to_symbol(str):
      return Symbol(str)
  
  
  def to_obj(tkn, lineno):
      try:
          return int(tkn)
      except:
          pass
      try:
          return float(tkn)
      except:
          pass
      try:
          return complex(tkn)
      except:
          pass
  
      if tkn[0] == ':':
          return Keyword(tkn[1:], lineno)
      else:
          return Symbol(tkn, lineno)
  
  
  class SexpReader(object):
      def __init__(self, port):
          object.__init__(self)
          self.port = port
          self.nest_level = 0
          self.line = 1
          self.commands = ("'", '(', ',', '`', '"', ';', '@', '~', '[', '{')
          self.white_spaces = (' ', '\r', '\n', '\t')
          self.separations = self.commands + self.white_spaces + (')', '~', ']', '}', EOF, '#')
          self.reader = SexpReader
          self.reader_macro_table = {
              '(': self.make_list_macro,
              '{': self.make_dict_macro,
              '!': self.make_ref_macro,
              'r': self.make_regexp_macro
          }
  
      def make_list_macro(self):
          sexp = [MAKE_LIST]
          sexp.extend(self.read_delimited_list(')'))
          return sexp
  
      def make_dict_macro(self):
          sexp = [MAKE_DICT]
          sexp.extend(self.read_delimited_list('}'))
          return sexp
  
      def make_regexp_macro(self):
          self.port.get_char()
          return RE_COMPILE, self.get_sexp()
  
      def make_ref_macro(self):
          self.port.get_char()
          return GET_REF, self.get_sexp()
  
      def has_reader_macro(self, char):
          return char in self.reader_macro_table.keys()
  
      def get_reader_macro(self, char):
          return self.reader_macro_table[char]
  
      def get_str(self):
          retval = ''
          while not self.port.next_char() == '"':
              char = self.port.get_char()
              if char is EOF:
                  raise Exception('Read error at "' + self.port.filename + '":line ' +
                                  str(self.line) + ' : EOF encountered in a string literal')
              if char == '\\':
                  try:
                      char = self.port.get_char()
                      if char == 'n':
                          char = "\n"
                      elif char == 't':
                          char = "\t"
                      elif char == 'r':
                          char = "\r"
                  except:
                      raise Exception("...")
              retval = retval + char
          self.port.get_char()
          return retval
  
      def skip_white_spaces(self):
          while self.port.next_char() in self.white_spaces:
              if self.port.next_char() == '\n':
                  self.line += 1
              self.port.get_char()
  
      def skip_until_newline(self):
          while not self.port.next_char() in {'\n', EOF}:
              self.port.get_char()
  
      def read_until_separation(self):
          retval = ''
          line = self.line
          self.skip_white_spaces()
          while not self.port.next_char() in self.separations:
              retval = retval + self.port.get_char()
          self.skip_white_spaces()
          return retval, line
  
      def read_delimited_list(self, right_delim):
          self.nest_level += 1
          self.port.get_char()
          retval = []
          while True:
              tkn, _ = self.read_until_separation()
              if tkn != '':
                  sexp = self.get_sexp(tkn)
                  if sexp is not COMMENT:
                      retval.append(sexp)
              if self.port.next_char() == right_delim:
                  self.nest_level -= 1
                  self.port.get_char()
                  break
              if self.port.next_char() == EOF:
                  break
              sexp = self.get_sexp()
              if sexp is not COMMENT:
                  retval.append(sexp)
          return retval
  
      def _compute_underscore_max_num(self, exps):
          max_num = 0
          for exp in exps:
              if isinstance(exp, Symbol) and exp.name.startswith('_'):
                  try:
                      n = int(exp.name[1:])
                  except:
                      n = 1
              elif issequence_except_str(exp):
                  n = self._compute_underscore_max_num(exp)
              else:
                  n = 0
  
              if n > max_num:
                  max_num = n
          return max_num
  
      def _create_underscore_args(self, exps):
          max_num = self._compute_underscore_max_num(exps)
          if max_num == 1:
              return [UNDERSCORE]
          else:
              return [Symbol('_' + str(n)) for n in range(1, max_num + 1)]
  
      def get_sexp(self, tkn=None):
          if tkn is None:
              tkn, line = self.read_until_separation()
          else:
              line = self.line
  
          if tkn is EOF:
              return EOF
          elif tkn != '':
              return to_obj(tkn, line)
          elif self.port.next_char() == ';':
              self.skip_until_newline()
              return COMMENT
          elif self.port.next_char() == '(':
              return self.read_delimited_list(')')
          elif self.port.next_char() == '~':
              rest_exps = self.read_delimited_list('~')
              return [FN, self._create_underscore_args(rest_exps), rest_exps]
          elif self.port.next_char() == '[':
              sexp = [MAKE_TUPLE]
              sexp.extend(self.read_delimited_list(']'))
              return sexp
          elif self.port.next_char() == '{':
              sexp = [TABLE]
              sexp.extend(self.read_delimited_list('}'))
              return sexp
          elif self.port.next_char() == "'":
              self.port.get_char()
              sexp = self.get_sexp()
              while sexp is COMMENT:
                  sexp = self.get_sexp()
              return [QUOTE, sexp]
          elif self.port.next_char() == '`':
              self.port.get_char()
              sexp = self.get_sexp()
              while sexp is COMMENT:
                  sexp = self.get_sexp()
              return [QUASIQUOTE, sexp]
          elif self.port.next_char() == ',':
              self.port.get_char()
              if self.port.next_char() == '@':
                  self.port.get_char()
                  sexp = self.get_sexp()
                  while sexp is COMMENT:
                      sexp = self.get_sexp()
                  return [UNQUOTE_SPLICING, sexp]
              else:
                  sexp = self.get_sexp()
                  while sexp is COMMENT:
                      sexp = self.get_sexp()
                  return [UNQUOTE, sexp]
          elif self.port.next_char() == '"':
              self.port.get_char()
              return self.get_str()
          elif self.port.next_char() == '#':
              if self.has_reader_macro(self.port.next_next_char()):
                  reader_macro = self.get_reader_macro(self.port.next_next_char())
                  self.port.get_char()
                  return reader_macro()
              else:
                  raise ReadError(self.port.filename, self.line, self.nest_level)
          elif self.port.next_char() == ')':
              raise ReadError(self.port.filename, self.line, self.nest_level)
          elif self.port.next_char() == '@':
              self.port.get_char()
              with_decorator_sexp = [WITH_DECORATOR]
              self.nest_level += 1
              while True:
                  decorator_sexp = self.get_sexp()
                  if decorator_sexp is EOF:
                      break
                  with_decorator_sexp.append(decorator_sexp)
                  if issequence_except_str(decorator_sexp) and decorator_sexp[0] == DEF:
                      self.nest_level -= 1
                      break
              return with_decorator_sexp
          else:
              return EOF
  
  
  #---------------------------------------------------------
  # Port Classes
  class InputPort(object):
      def __init__(self, file=sys.__stdin__):
          self._closed = False
          self.file = file
          self.filename = '<string>' if isinstance(file, StringIO) else file.name
          self.buffer = ''
  
      def get_char(self):
          if len(self.buffer) == 0:
              c = self.file.read(1)
              if len(c) == 0:
                  return EOF
              return c
          retval = self.buffer[0]
          self.buffer = self.buffer[1:]
          return retval
  
      def next_char(self):
          if len(self.buffer) == 0:
              c = self.file.read(1)
              if len(c) == 0:
                  return EOF
              self.buffer = c
          return self.buffer[0]
  
      def next_next_char(self):
          if len(self.buffer) == 0:
              c = self.file.read(1)
              if len(c) == 0:
                  return EOF
              self.buffer = c
              c = self.file.read(1)
              if len(c) == 0:
                  return EOF
              self.buffer = self.buffer + c
          elif len(self.buffer) == 1:
              c = self.file.read(1)
              if len(c) == 0:
                  return EOF
              self.buffer = self.buffer + c
          return self.buffer[1]
  
      def _read(self):
          if self._closed:
              raise Exception('error!')
          else:
              sr = SexpReader(self)
              while True:
                  retval = sr.get_sexp()
                  if retval is not COMMENT:
                      break
              return retval
  
      def _close(self):
          self._closed = True
          return None
  
  
  class OutputPort(object):
      def __init__(self, file=sys.__stdout__):
          self.file = file
  
      def display(self, arg):
          port = self.file
          sexpr = arg
          ol = []
          stack = [sexpr]
  
          while len(stack) > 0:
              sexpr = stack.pop()
              if is_tuple_or_list(sexpr):
                  stack.append(RPARA)
                  rsexpr = []
                  for sub in sexpr:
                      rsexpr.insert(0, sub)
                  stack.extend(rsexpr)
                  stack.append(LPARA)
              else:
                  ol.append(sexpr)
  
          retval = ''
          olditem = ''
          for item in ol:
              if type(item) is str:
                  if not ((item is RPARA) or (olditem is LPARA)):
                      item = ' ' + item
                  retval += item
              else:
                  sitem = str(item)
                  if not ((item is RPARA) or (olditem is LPARA)):
                      sitem = ' ' + sitem
                  retval += sitem
              olditem = item
          port.write(retval[1:])
          return None
  
      def write(self, obj):
          self.file.write(str(obj))  # emit_sexp(obj)) repr
          return None
  
  
  current_input_port = InputPort()
  current_output_port = OutputPort()
  current_error_port = OutputPort(file=sys.__stderr__)
  
  
  @builtin
  def display(obj):
      return current_output_port.display(obj)
  
  
  @builtin
  def write(obj, end='\n'):
      if obj is not None:
          current_output_port.write(obj)
          current_output_port.write(end)
  
  
  @builtin
  def format(s, *args, **kwargs):
      return s.format(*args, **kwargs)
  
  
  @builtin
  def zero(arg):
      return arg == 0
  
  
  @builtin
  def positive(arg):
      return arg > 0
  
  
  @builtin
  def negative(arg):
      return arg < 0
  
  
  @builtin
  def odd(arg):
      return type(arg) is int and bool(arg % 2)
  
  
  @builtin
  def even(arg):
      return type(arg) is int and not bool(arg % 2)
  
  
  @builtin
  def caar(seq):
      return seq[0][0]
  
  
  @builtin
  @builtin_rename('second')
  def cadr(seq):
      return seq[1]
  
  
  @builtin
  def cdar(seq):
      return seq[0][1:]
  
  
  @builtin
  def cddr(seq):
      return seq[2:]
  
  
  @builtin
  def caaar(seq):
      return seq[0][0][0]
  
  
  @builtin
  def caadr(seq):
      return seq[1][0]
  
  
  @builtin
  def cadar(seq):
      return seq[0][1]
  
  
  @builtin
  @builtin_rename('third')
  def caddr(seq):
      return seq[2]
  
  
  @builtin
  @builtin_rename('fourth')
  def cadddr(seq):
      return seq[3]
  
  
  @builtin
  def cdaar(seq):
      return seq[0][0][1:]
  
  
  @builtin
  def cdadr(seq):
      return seq[1][1:]
  
  
  @builtin
  def cddar(seq):
      return seq[0][2:]
  
  
  @builtin
  def cdddr(seq):
      return seq[3:]
  
  
  @builtin
  def null(obj):
      return obj == () or obj is None or (issequence(obj) and len(obj) == 0)
  
  
  @builtin
  class cell(Sequence):
      __slots__ = ('_head', '_tail')
  
      def __init__(self, head, tail=None):
          self._head = head
          if isinstance(tail, cell) or (tail is None):
              self._tail = tail
          else:
              raise TypeError('tail: expected None or cell, but ' + type(tail) + ' found')
  
      def __getitem__(self, index):
          if isinstance(index, slice):
              start = index.start
              pos_index = start if start >= 0 else self.__len__() + start
          else:
              start = None
              pos_index = index if index >= 0 else self.__len__() + index
  
          item = self
          while pos_index > 0:
              if isinstance(item, cell):
                  item = item._tail
              else:
                  raise IndexError('index out of range')
              pos_index -= 1
  
          if start is None:
              if item is None:
                  raise IndexError('index out of range')
              return item._head
  
          return item
  
      def __len__(self):
          length = 0
          item = self
          while True:
              if isinstance(item, cell):
                  item = item._tail
                  length += 1
              else:
                  return length
  
      def __repr__(self):
          repr_strs = ['L(']
          for item in self:
              repr_strs.append(repr(item))
              repr_strs.append(' ')
          if len(repr_strs) == 0:
              repr_strs.append(')')
          else:
              repr_strs[-1] = ')'
  
          return ''.join(repr_strs)
  
  
  @builtin_rename('clist')
  @builtin_rename('cell*')
  def make_cell_list(*args):
      lis = None
      for arg in reversed(args):
          lis = cell(arg, lis)
      return lis
  
  
  @builtin
  class lazyseq(Sequence):
      def __init__(self, iterable):
          self._cache = []
          self._iterator = iter(iterable)
  
      def __getitem__(self, index):
          if isinstance(index, slice):
              start = index.start if index.start >= 0 else len(self) + index.start
              stop = len(self) if index.stop is None else index.stop if index.stop >= 0 else len(self) + index.stop
              try:
                  len_cache = len(self._cache)
                  while len_cache < stop:
                      self._cache.append(next(self._iterator))
                      len_cache += 1
              except StopIteration:
                  raise IndexError('index out of range')
              return self._cache[slice(start, stop, index.step)]
          else:
              pos_index = index if index >= 0 else len(self) + index
              try:
                  len_cache = len(self._cache)
                  while len_cache <= pos_index:
                      self._cache.append(next(self._iterator))
                      len_cache += 1
              except StopIteration:
                  raise IndexError('index out of range')
              return self._cache[pos_index]
  
      def __len__(self):
          self._cache.extend(list(self._iterator))
          return len(self._cache)
  
      def __repr__(self):
          return 'lazyseq(' + repr(self._iterator) + ')'
  
      def __call__(self, index, *rest):
          len_rest = len(rest)
          if len_rest == 1:
              return self.__getitem__(slice(index, rest[0]))
          elif len_rest == 2:
              return self.__getitem__(slice(index, rest[0], rest[1]))
          elif len_rest >= 3:
              slice(index, *rest)
          else:
              return self.__getitem__(index)
  
  
  @builtin
  def table(*keyvalues, **somedict):
      return pmap(dict(chunks(keyvalues, 2), **somedict))
  
  
  @builtin
  def listtab(lis):
      return table(*lis)
  
  
  @builtin
  def tablist(tabl):
      return tuple(tabl.items())
  
  
  @builtin
  def getslice(seq, start, end=None, step=1):
      return seq[start:end:step]
  
  
  @builtin
  def curried(func):
      arg_count = func.__code__.co_argcount
      l = ['lambda arg_{0}: '.format(n) for n in range(arg_count)]
      l.append('func(')
      l.extend(['arg_{0}, '.format(n) for n in range(arg_count - 1)])
      l.extend(['arg_', str(arg_count - 1), ')'])
      return eval(''.join(l), {'func': func})
  
  
  @builtin
  def rcurried(func):
      argcount = func.__code__.co_argcount
      l = ['lambda arg_{0}: '.format(n) for n in range(argcount - 1, -1, -1)]
      l.append('func(')
      l.extend(['arg_{0}, '.format(n) for n in range(argcount - 1)])
      l.extend(['arg_', str(argcount - 1), ')'])
      return eval(''.join(l), {'func': func})
  
  
  @builtin
  def auto_partial(func):
      if isinstance(func, partial):
          args_count = 0
          inner_func = func
          while isinstance(inner_func, partial):
              args_count += len(inner_func.args)
              inner_func = inner_func.func
          original_func_argcount = inner_func.__code__.co_argcount
          func_argcount = original_func_argcount - args_count
      else:
          func_argcount = func.__code__.co_argcount
  
      def _partial(*args):
          if (func_argcount - len(args)) <= 0:
              return func(*args)
          else:
              return auto_partial(partial(func, *args))
  
      return _partial
  
  
  @builtin
  def apply(func, args, kwargs=None):
      if kwargs is None:
          return func(*args)
      else:
          return func(*args, **kwargs)
  
  
  @builtin
  def compose(*funcs, unpack=False):
      reversed_funcs = list(reversed(funcs))
  
      def composed_func(*args, **kwargs):
          retval = reversed_funcs[0](*args, **kwargs)
          if unpack:
              for func in reversed_funcs[1:]:
                  retval = func(*retval)
                  return retval
          else:
              for func in reversed_funcs[1:]:
                  retval = func(retval)
                  return retval
  
      return composed_func
  
  
  @builtin
  def conjoin(*funcs):
      def conjoined_func(*args, **kwargs):
          retval = True
          for func in funcs:
              retval = retval and func(*args, **kwargs)
              if not retval:
                  break
          return retval
  
      return conjoined_func
  
  
  @builtin
  def disjoin(*funcs):
      def disjoined_func(*args, **kwargs):
          retval = False
          for func in funcs:
              retval = retval or func(*args, **kwargs)
              if retval:
                  break
          return retval
  
      return disjoined_func
  
  
  @builtin
  def compare(comparer, scorer):
      return lambda arg1, arg2: comparer(scorer(arg1), scorer(arg2))
  
  
  @builtin
  def complement(func):
      return lambda *args, **kwargs: not (func(*args, **kwargs))
  
  
  @builtin
  def ref(value):
      # getter
      def _0():
          return value
  
      # setter
      def _1(update_func):
          nonlocal value
          value = update_func(value)
          return value
  
      return _0, _1
  
  
  #@builtin_rename('set!')
  #def update_ref(ref, update_func):
  #    return ref[1](update_func)
  
  
  def _check_duplicated_binding_name(symbol, filename, lis):
      constant_name = symbol.name
      for constant_name_set in reversed(lis):
          if constant_name in constant_name_set:
              raise DuplicatedDefError(symbol, filename)
          if not constant_name_set.quasi:
              break
      lis[-1].add(constant_name)
      return symbol
  
  
  def check_duplicated_binding_name(symbol, filename):
      return symbol
      # return _check_duplicated_binding_name(symbol, filename, binding_name_set_stack)
  
  
  def check_duplicated_binding_name_outer(symbol, filename):
      binding_name_set_stack[-2].add(symbol.name)
      return symbol
  
  
  def check_duplicated_binding(sexps, filename):
      for sexp in sexps:
          if not issequence_except_str(sexp):
              continue
          if not isinstance(sexp[0], Symbol):
              continue
          tag = sexp[0].name
          current_set = binding_name_set_stack[-1]
          if tag in {'_val', 'def', 'mac'}:
              binding_symbol = sexp[1]
              binding_name = binding_symbol.name
              if binding_name in current_set:
                  raise DuplicatedDefError(binding_symbol, filename)
              current_set.add(binding_name)
      return sexps
  
  
  @builtin
  def unquote_splice(lis):
      newlis = []
      splicing_flag = False
      for item in lis:
          if type(item) is Symbol and item.name == '_mochi_unquote_splicing':
              splicing_flag = True
          else:
              if splicing_flag:
                  newlis.extend(item)
                  splicing_flag = False
              else:
                  newlis.append(item)
  
      if type(lis) is list:
          return newlis
      elif type(lis) is tuple:
          return tuple(newlis)
      else:
          try:
              return type(lis)(newlis)
          except:
              raise UnquoteSplicingError()
  
  
  @builtin
  def tuple_it(obj):
      return tuple(map(tuple_it, obj)) if isinstance(obj, MutableSequence) else obj
  
  
  def eval_tokens(tokens, globals=global_env, locals=None):
      sexps = parse(tokens.__iter__())
      for sexp in sexps:
          if isinstance(sexp, MutableSequence):
              sexp = tuple_it(sexp)
          if sexp is COMMENT:
              continue
          py_ast = translator.translate_sexp_to_interact(sexp)
          if py_ast is not None:
              code = compile(py_ast, '<string>', 'exec')
              if code is not None:
                  exec(code, globals, locals)
  
  
  @builtin_rename('eval')
  def eval_code_block(block, globals=global_env, locals=None):
      lexer = lex(block + '\n', repl_mode=True)
      eval_tokens(lexer, globals, locals)
  
  
  def eval_sexp_str(sexp_str):
      sr = SexpReader(InputPort(StringIO(sexp_str)))
      while True:
          sexp = sr.get_sexp()
  
          if sexp is None:
              break
          if sexp is EOF:
              break
          if sexp is COMMENT:
              continue
  
          py_ast = translator.translate_sexp(tuple_it(sexp))
  
          if py_ast is not None:
              code = compile(py_ast, '<string>', 'exec')
              if code is not None:
                  exec(code, global_env)
  
  
  @builtin_rename('_del_hidden_var')
  def del_hidden_var(name):
      translator.hidden_vars.remove(name)
  
  
  @builtin_rename('_get_hidden_vars')
  def get_hidden_vars():
      return translator.hidden_vars
  
  
  @builtin_rename('delitem')
  def _del(name, env):
      del env[name]
  
  
  @builtin_rename('macex1')
  @builtin_rename('macroexpand_1')
  def macroexpand1(exp):
      if translator.is_macro(exp):
          return translator.expand_macro(exp[0].name, exp[1:])
      return exp
  
  
  @builtin
  @builtin_rename('macex')
  def macroexpand(exp):
      if translator.is_macro(exp):
          return macroexpand(macroexpand1(exp))
      return exp
  
  
  @builtin
  def is_macro(func):
      return isinstance(func, FunctionType) and translator.has_macro(func.__name__)
  
  
  @builtin
  def is_function(func):
      return isinstance(func, FunctionType) and (not translator.has_macro(func.__name__))
  
  
  @builtin
  def iter_except(func, exc):
      try:
          while 1:
              yield func()
      except exc:
          pass
  
  
  @builtin
  def assert_equal(value1, value2):
      assert value1 == value2
  
  
  @builtin
  def assert_not_equal(value1, value2):
      assert value1 != value2
  
  
  @builtin
  def assert_none(value):
      assert value is None
  
  
  @builtin
  def assert_not_none(value):
      assert value is not None
  
  
  @builtin
  def assert_same(value1, value2):
      assert value1 is value2
  
  
  @builtin
  def assert_not_same(value1, value2):
      assert value1 is not value2
  