# Path: pigeon/xerblin/base.py
# def handle_sequence(I, seq):
#     '''
#     Run a sequence and return the modified interpreter.
#     '''
#     for func in seq[1:]:
#         I = apply_func(I, func)
#     return I
# 
# def handle_loop(I, loop):
#     '''
#     Check TOS and do body if it's true, repeat.
#     '''
#     while True:
#         TOS, I = _pop_TOS(I)
#         if not TOS:
#             break
#         I = handle_sequence(I, loop)
#     return I
# 
# def handle_branch(I, branch):
#     '''
#     Check TOS and do one thing or another depending.
#     '''
#     TOS, I = _pop_TOS(I)
#     func = branch[(not TOS) + 1] # i.e. True = 1; False = 2
#     return apply_func(I, func)
# 
# def enstacken((stack, dictionary), stack_us):
#     '''
#     Push the items in the body onto the stack.
#     '''
#     stack = push(stack, *stack_us[1:])
#     return stack, dictionary
# 
# Path: pigeon/xerblin/btree.py
# def get(node, key):
#     '''
#     Return the value stored under key or raise KeyError if not found.
#     '''
#     if not node:
#         raise KeyError, key
# 
#     node_key, value, lower, higher = node
# 
#     if key == node_key:
#         return value
# 
#     return get(lower if key < node_key else higher, key)
# 
# def insert(node, key, value):
#     '''
#     Return a tree with value stored under key. Replaces old value if any.
#     '''
#     if not node:
#         return key, value, (), ()
# 
#     node_key, node_value, lower, higher = node
# 
#     if key < node_key:
#         return node_key, node_value, insert(lower, key, value), higher
# 
#     if key > node_key:
#         return node_key, node_value, lower, insert(higher, key, value)
# 
#     return key, value, lower, higher
# 
# def items(node):
#     '''
#     Iterate in order over the (key, value) pairs in a tree.
#     '''
#     if not node:
#         return
# 
#     key, value, lower, higher = node
#     
#     for kv in items(lower):
#         yield kv
#     
#     yield key, value
#     
#     for kv in items(higher):
#         yield kv
# 
# def fill_tree(node, items):
#     '''
#     Add the (key, value) pairs in items to a btree in a balanced way.
# 
#     You can balance a tree like so:
# 
#         tree = fill_tree((), items(tree))
# 
#     This iterates through the tree and returns a new, balanced tree from
#     its contents.
#     '''
#     for key, value in _yield_balanced(sorted(items)):
#         node = insert(node, key, value)
#     return node
# 
# Path: pigeon/xerblin/stack.py
# def pop(stack, number):
#     '''Pop number arguments from stack.'''
#     for _ in range(number):
#         item, stack = stack # pop
#         yield item
#     yield stack
# 
# def push(stack, *items):
#     '''Push arguments onto a stack.'''
#     for item in items:
#         stack = item, stack # push
#     return stack
# 
# def pick_(stack, n):
#     '''
#     Find the nth item on the stack and duplicate it to TOS. (Pick with
#     zero is the same as "dup".)
#     '''
#     if n < 0:
#         raise ValueError
#     s = stack
#     while True:
#         try:
#             item, s = s
#         except ValueError:
#             raise IndexError
#         n -= 1
#         if n < 0:
#             break
#     return item, stack
# 
# def iterStack(stack):
#     '''Iterate through the items on the stack.'''
#     while stack:
#         item, stack = stack
#         yield item
# 
# Path: pigeon/assembler/pyavrasm.py
# def assemble(self, text):
#   '''
#   Assemble the string asm source code.
# 
#   :param text: Assembly source code.
#   :type text: ``str``
#   :rtype: ``None``
#   '''
#   exec text in self.context
#   del self.context['__builtins__']
#   self.pass2()
# 
# Path: pigeon/metacompiler/metaii.py
# def comp(source, machine):
#   m2 = MetaII()
#   m2.assemble(machine)
#   return m2.compile(source)


from pickle import dumps, loads
from pigeon.xerblin.base import handle_sequence, handle_loop, handle_branch, enstacken
from pigeon.xerblin.btree import get, insert, items, fill_tree
from pigeon.xerblin.stack import pop, push, pick_, iterStack
from pigeon.assembler.pyavrasm import assemble as assemble_raw
from pigeon.metacompiler.metaii import comp
    from pprint import pprint as p

def pickle(interpreter):
    '''
    Convert the current interpreter to a portable text format (called a
    "pickle".)
    '''
    stack, dictionary = interpreter
    p = dumps(interpreter)
    return (p, stack), dictionary


def unpickle(interpreter):
    '''
    Take a string "pickle" portable text representation of an interpreter
    and replace the current interpreter with it.
    '''
    stack = interpreter[0]
    return loads(stack[0])


# System words

def rebalance((stack, dictionary)):
    '''
    This "rebalances" a dictionary.  It makes it more efficient to access
    commands in the dictionary if you've added a lot of new ones.

    It's a good idea to use this command before creating a pickle to
    save so that the saved pickle's dictionary is already balanced.
    '''

# Path: pigeon/xerblin/base.py
# def handle_sequence(I, seq):
#     '''
#     Run a sequence and return the modified interpreter.
#     '''
#     for func in seq[1:]:
#         I = apply_func(I, func)
#     return I
# 
# def handle_loop(I, loop):
#     '''
#     Check TOS and do body if it's true, repeat.
#     '''
#     while True:
#         TOS, I = _pop_TOS(I)
#         if not TOS:
#             break
#         I = handle_sequence(I, loop)
#     return I
# 
# def handle_branch(I, branch):
#     '''
#     Check TOS and do one thing or another depending.
#     '''
#     TOS, I = _pop_TOS(I)
#     func = branch[(not TOS) + 1] # i.e. True = 1; False = 2
#     return apply_func(I, func)
# 
# def enstacken((stack, dictionary), stack_us):
#     '''
#     Push the items in the body onto the stack.
#     '''
#     stack = push(stack, *stack_us[1:])
#     return stack, dictionary
# 
# Path: pigeon/xerblin/btree.py
# def get(node, key):
#     '''
#     Return the value stored under key or raise KeyError if not found.
#     '''
#     if not node:
#         raise KeyError, key
# 
#     node_key, value, lower, higher = node
# 
#     if key == node_key:
#         return value
# 
#     return get(lower if key < node_key else higher, key)
# 
# def insert(node, key, value):
#     '''
#     Return a tree with value stored under key. Replaces old value if any.
#     '''
#     if not node:
#         return key, value, (), ()
# 
#     node_key, node_value, lower, higher = node
# 
#     if key < node_key:
#         return node_key, node_value, insert(lower, key, value), higher
# 
#     if key > node_key:
#         return node_key, node_value, lower, insert(higher, key, value)
# 
#     return key, value, lower, higher
# 
# def items(node):
#     '''
#     Iterate in order over the (key, value) pairs in a tree.
#     '''
#     if not node:
#         return
# 
#     key, value, lower, higher = node
#     
#     for kv in items(lower):
#         yield kv
#     
#     yield key, value
#     
#     for kv in items(higher):
#         yield kv
# 
# def fill_tree(node, items):
#     '''
#     Add the (key, value) pairs in items to a btree in a balanced way.
# 
#     You can balance a tree like so:
# 
#         tree = fill_tree((), items(tree))
# 
#     This iterates through the tree and returns a new, balanced tree from
#     its contents.
#     '''
#     for key, value in _yield_balanced(sorted(items)):
#         node = insert(node, key, value)
#     return node
# 
# Path: pigeon/xerblin/stack.py
# def pop(stack, number):
#     '''Pop number arguments from stack.'''
#     for _ in range(number):
#         item, stack = stack # pop
#         yield item
#     yield stack
# 
# def push(stack, *items):
#     '''Push arguments onto a stack.'''
#     for item in items:
#         stack = item, stack # push
#     return stack
# 
# def pick_(stack, n):
#     '''
#     Find the nth item on the stack and duplicate it to TOS. (Pick with
#     zero is the same as "dup".)
#     '''
#     if n < 0:
#         raise ValueError
#     s = stack
#     while True:
#         try:
#             item, s = s
#         except ValueError:
#             raise IndexError
#         n -= 1
#         if n < 0:
#             break
#     return item, stack
# 
# def iterStack(stack):
#     '''Iterate through the items on the stack.'''
#     while stack:
#         item, stack = stack
#         yield item
# 
# Path: pigeon/assembler/pyavrasm.py
# def assemble(self, text):
#   '''
#   Assemble the string asm source code.
# 
#   :param text: Assembly source code.
#   :type text: ``str``
#   :rtype: ``None``
#   '''
#   exec text in self.context
#   del self.context['__builtins__']
#   self.pass2()
# 
# Path: pigeon/metacompiler/metaii.py
# def comp(source, machine):
#   m2 = MetaII()
#   m2.assemble(machine)
#   return m2.compile(source)


# Path: pigeon/xerblin/library.py
from pickle import dumps, loads
from pigeon.xerblin.base import handle_sequence, handle_loop, handle_branch, enstacken
from pigeon.xerblin.btree import get, insert, items, fill_tree
from pigeon.xerblin.stack import pop, push, pick_, iterStack
from pigeon.assembler.pyavrasm import assemble as assemble_raw
from pigeon.metacompiler.metaii import comp
    from pprint import pprint as p


def pickle(interpreter):
    '''
    Convert the current interpreter to a portable text format (called a
    "pickle".)
    '''
    stack, dictionary = interpreter
    p = dumps(interpreter)
    return (p, stack), dictionary


def unpickle(interpreter):
    '''
    Take a string "pickle" portable text representation of an interpreter
    and replace the current interpreter with it.
    '''
    stack = interpreter[0]
    return loads(stack[0])


# System words

def rebalance((stack, dictionary)):
    '''
    This "rebalances" a dictionary.  It makes it more efficient to access
    commands in the dictionary if you've added a lot of new ones.

    It's a good idea to use this command before creating a pickle to
    save so that the saved pickle's dictionary is already balanced.
    '''

    dictionary = fill_tree((), items(dictionary))