예제 #1
0
def _action_stack_to_python(block, tw, name='start'):
    """ Turn a stack of blocks into Python code
    name -- the name of the action stack (defaults to "start") """

    if isinstance(name, int):
        name = float(name)
    if not isinstance(name, basestring):
        name = str(name)

    # traverse the block stack and get the AST for every block
    ast_list = _walk_action_stack(block, tw.lc)
    if not ast_list or not isinstance(ast_list[-1], ast.Yield):
        ast_list.append(ast_yield_true())
    action_stack_ast = ast.Module(body=ast_list)

    # serialize the ASTs into python code
    generated_code = codegen.to_source(action_stack_ast)

    # wrap the action stack setup code around everything
    name_id = _make_identifier(name)
    if name == 'start':
        pre_preamble = _START_STACK_START_ADD
        for k in plugins_in_use:
            pre_preamble += '    global %s\n' % (k.lower(),)
            pre_preamble += "    %s = global_objects['%s']\n" % (k.lower(), k)
    else:
        pre_preamble = ''
    generated_code = _indent(generated_code, 1)
    if generated_code.endswith(linesep):
        newline = ''
    else:
        newline = linesep
    snippets = [_ACTION_STACK_START % (name_id),
                pre_preamble,
                _ACTION_STACK_PREAMBLE,
                generated_code,
                newline,
                _ACTION_STACK_END % (name, name_id)]
    return ''.join(snippets)
def _action_stack_to_python(block, tw, name='start'):
    """ Turn a stack of blocks into Python code
    name -- the name of the action stack (defaults to "start") """

    if isinstance(name, int):
        name = float(name)
    if not isinstance(name, basestring):
        name = str(name)

    # traverse the block stack and get the AST for every block
    ast_list = _walk_action_stack(block, tw.lc)
    if not ast_list or not isinstance(ast_list[-1], ast.Yield):
        ast_list.append(ast_yield_true())
    action_stack_ast = ast.Module(body=ast_list)

    # serialize the ASTs into python code
    generated_code = codegen.to_source(action_stack_ast)

    # wrap the action stack setup code around everything
    name_id = _make_identifier(name)
    if name == 'start':
        pre_preamble = _START_STACK_START_ADD
        for k in plugins_in_use:
            pre_preamble += '    global %s\n' % (k.lower(),)
            pre_preamble += "    %s = global_objects['%s']\n" % (k.lower(), k)
    else:
        pre_preamble = ''
    generated_code = _indent(generated_code, 1)
    if generated_code.endswith(linesep):
        newline = ''
    else:
        newline = linesep
    snippets = [_ACTION_STACK_START % (name_id),
                pre_preamble,
                _ACTION_STACK_PREAMBLE,
                generated_code,
                newline,
                _ACTION_STACK_END % (name, name_id)]
    return ''.join(snippets)
예제 #3
0
def _walk_action_stack(top_block, lc, convert_me=True):
    """ Turn a stack of blocks into a list of ASTs
    convert_me -- convert values and Primitives to ASTs or return them
        unconverted? """
    block = top_block

    # value blocks don't have a primitive
    # (but constant blocks (colors, screen dimensions, etc.) do)
    if block.is_value_block():
        raw_value = block.get_value(add_type_prefix=False)
        if convert_me:
            value_ast = value_to_ast(raw_value)
            if value_ast is not None:
                return [value_ast]
            else:
                return []
        else:
            if raw_value is not None:
                return [raw_value]
            else:
                return []

    def _get_prim(block):
        prim = lc.get_prim_callable(block.primitive)
        # fail gracefully if primitive is not a Primitive object
        if not isinstance(prim, Primitive):
            raise PyExportError(_("block is not exportable"), block=block)
        return prim

    prim = _get_prim(block)

    ast_list = []
    arg_asts = []

    def _finish_off(block, prim=None):
        """ Convert block to an AST and add it to the ast_list. Raise a
        PyExportError on failure. """
        if prim is None:
            prim = _get_prim(block)
        if convert_me:
            if prim.export_me:
                try:
                    new_ast = prim.get_ast(*arg_asts)
                except ValueError:
                    traceback.print_exc()
                    raise PyExportError(_("error while exporting block"),
                                        block=block)
                if isinstance(new_ast, (list, tuple)):
                    ast_list.extend(new_ast)
                elif new_ast is not None:
                    ast_list.append(new_ast)
            elif arg_asts:  # TODO do we ever get here?
                new_ast = ast.List(elts=arg_asts, ctx=ast.Load)
                ast_list.append(new_ast)
        else:
            ast_list.append((prim, ) + tuple(arg_asts))

    # skip the very first dock/ connection - it's either the previous block or
    # the return value of this block
    dock_queue = block.docks[1:]
    conn_queue = block.connections[1:]
    while dock_queue and conn_queue:
        dock = dock_queue.pop(0)
        conn = conn_queue.pop(0)
        if conn is None or dock[0] == 'unavailable':
            continue
        elif not dock_queue and dock[0] == 'flow':
            # finish off this block
            _finish_off(block, prim)
            arg_asts = []
            # next block
            block = conn
            prim = _get_prim(block)
            dock_queue = block.docks[1:]
            conn_queue = block.connections[1:]
        else:
            # embedded stack of blocks (body of conditional or loop) or
            # argument block
            if dock[0] == 'flow':
                # body of conditional or loop
                new_arg_asts = _walk_action_stack(conn,
                                                  lc,
                                                  convert_me=convert_me)
                if (prim == LogoCode.prim_loop
                        and not isinstance(new_arg_asts[-1], ast.Yield)):
                    new_arg_asts.append(ast_yield_true())
                arg_asts.append(new_arg_asts)
            else:
                # argument block
                new_arg_asts = _walk_action_stack(conn, lc, convert_me=False)
                arg_asts.append(*new_arg_asts)

    # finish off last block
    _finish_off(block, prim)

    return ast_list
예제 #4
0
def _walk_action_stack(top_block, lc, convert_me=True):
    """ Turn a stack of blocks into a list of ASTs
    convert_me -- convert values and Primitives to ASTs or return them
        unconverted? """
    block = top_block

    # value blocks don't have a primitive
    # (but constant blocks (colors, screen dimensions, etc.) do)
    if block.is_value_block():
        raw_value = block.get_value(add_type_prefix=False)
        if convert_me:
            value_ast = value_to_ast(raw_value)
            if value_ast is not None:
                return [value_ast]
            else:
                return []
        else:
            if raw_value is not None:
                return [raw_value]
            else:
                return []

    def _get_prim(block):
        prim = lc.get_prim_callable(block.primitive)
        # fail gracefully if primitive is not a Primitive object
        if not isinstance(prim, Primitive):
            raise PyExportError(_("block is not exportable"), block=block)
        return prim

    prim = _get_prim(block)

    ast_list = []
    arg_asts = []

    def _finish_off(block, prim=None):
        """ Convert block to an AST and add it to the ast_list. Raise a
        PyExportError on failure. """
        if prim is None:
            prim = _get_prim(block)
        if convert_me:
            if prim.export_me:
                try:
                    new_ast = prim.get_ast(*arg_asts)
                except ValueError:
                    traceback.print_exc()
                    raise PyExportError(_("error while exporting block"),
                                        block=block)
                if isinstance(new_ast, (list, tuple)):
                    ast_list.extend(new_ast)
                elif new_ast is not None:
                    ast_list.append(new_ast)
            elif arg_asts:  # TODO do we ever get here?
                new_ast = ast.List(elts=arg_asts, ctx=ast.Load)
                ast_list.append(new_ast)
        else:
            ast_list.append((prim, ) + tuple(arg_asts))

    # skip the very first dock/ connection - it's either the previous block or
    # the return value of this block
    dock_queue = block.docks[1:]
    conn_queue = block.connections[1:]
    while dock_queue and conn_queue:
        dock = dock_queue.pop(0)
        conn = conn_queue.pop(0)
        if conn is None or dock[0] == 'unavailable':
            continue
        elif not dock_queue and dock[0] == 'flow':
            # finish off this block
            _finish_off(block, prim)
            arg_asts = []
            # next block
            block = conn
            prim = _get_prim(block)
            dock_queue = block.docks[1:]
            conn_queue = block.connections[1:]
        else:
            # embedded stack of blocks (body of conditional or loop) or
            # argument block
            if dock[0] == 'flow':
                # body of conditional or loop
                new_arg_asts = _walk_action_stack(conn, lc,
                                                  convert_me=convert_me)
                if (prim == LogoCode.prim_loop and
                        not isinstance(new_arg_asts[-1], ast.Yield)):
                    new_arg_asts.append(ast_yield_true())
                arg_asts.append(new_arg_asts)
            else:
                # argument block
                new_arg_asts = _walk_action_stack(conn, lc, convert_me=False)
                arg_asts.append(*new_arg_asts)

    # finish off last block
    _finish_off(block, prim)

    return ast_list