def macro_expand(self, fn_symbol, ast_node, words_needed):
     _, condition, true_branch, false_branch = ast_node.args
     endif_label = crud.gensym('endif')
     if false_branch is None:
         new_args = (
           ast.ast.from_parser(condition.get_syntax_position_info(),
                               condition,
                               kind='if-false',
                               label=endif_label,
                               expect='statement'),
           true_branch,
           ast.ast(kind='label', label=endif_label, expect='statement'),
         )
     else:
         else_label = crud.gensym('else')
         new_args = (
           ast.ast.from_parser(condition.get_syntax_position_info(),
                               condition,
                               kind='if-false',
                               label=else_label,
                               expect='statement'),
           true_branch,
           ast.ast(kind='jump', label=endif_label, expect='statement'),
           ast.ast(kind='label', label=else_label, expect='statement'),
           false_branch,
           ast.ast(kind='label', label=endif_label, expect='statement'),
         )
     return ast_node.macro_expand(fn_symbol, words_needed, new_args,
                                  kind='series')
    def macro_expand(self, fn_symbol, ast_node, words_needed):
        r'''This macro expands to an set-output-bit.

        set-output-bit port_name bit#
        '''
        assert len(ast_node.args) == 2
        assert len(ast_node.args[1]) == 1, \
               "%s: incorrect number of arguments, expected 1, got %s" % \
                 (self.label, len(ast_node.args[1]))
        fn_symbol.side_effects = 1
        pin = ast_node.args[1][0]
        #print "toggle: pin", pin, pin.symbol_id, pin.label
        pin_number = \
          symbol_table.get_by_id(pin.symbol_id).word_word \
                      .get_value('pin_number')
        port_label, bit_number = output_pin.digital_pin_lookup[pin_number]
        #print "toggle: port_label", port_label, ", bit_number", bit_number
        ioreg_bit = ast.ast(kind='ioreg-bit',
                            label='io.pin' + port_label, int1=bit_number)
        new_args = (
            ast.ast.word('set-output-bit'),
            (ioreg_bit,),
        )
        return ast_node.macro_expand(fn_symbol, words_needed, new_args,
                                     kind='call')
    def macro_expand(self, fn_symbol, ast_node, words_needed):
        r'''This macro expands to an if statement.

        if arg:
            set-output-bit ioreg-bit
        else:
            clear-output-bit ioreg-bit

        or

        if arg:
            clear-output-bit ioreg-bit
        else:
            set-output-bit ioreg-bit

        depending on on-is setting.
        '''
        assert len(ast_node.args) == 2
        assert len(ast_node.args[1]) == 1, \
               "%s: incorrect number of arguments, expected 1, got %s" % \
                 (self.label, len(ast_node.args[1]))
        fn_symbol.side_effects = 1
        pin_number = self.ww.get_value('pin_number')
        on_is = self.ww.get_answer('on_is').tag
        port_label, bit_number = digital_pin_lookup[pin_number]
        print "output_pin: port_label", port_label, ", bit_number", bit_number
        ioreg_bit = ast.ast(kind='ioreg-bit',
                            label='io.port' + port_label, int1=bit_number)
        if on_is == 'HIGH':
            true_call = 'set-output-bit'
            false_call = 'clear-output-bit'
        else:
            true_call = 'clear-output-bit'
            false_call = 'set-output-bit'
        new_args = (
            ast.ast.word('if'),
            ast_node.args[1][0],
            (ast.ast.call(true_call, ioreg_bit, expect='statement'),),
            (ast.ast.call(false_call, ioreg_bit, expect='statement'),),
        )
        return ast_node.macro_expand(fn_symbol, words_needed, new_args,
                                     kind='call')
    def macro_expand(self, fn_symbol, ast_node, words_needed):
        #print "repeat.macro_expand"
        _, count, body = ast_node.args
        loop_label = crud.gensym('repeat')
        if not count:
            #print "no count"
            new_args = (
              ast.ast(kind='label', label=loop_label, expect='statement'),
              body,
              ast.ast(kind='jump', label=loop_label, expect='statement'),
            )
        else:
            count = count[0]
            #print "count", count
            if count.kind == 'int':
                assert count.int1 >= 0, \
                       "repeat must not have negative repeat count"
                if count.int1 == 0:
                    return ast_node.macro_expand(fn_symbol, words_needed, (),
                                                 kind='no-op')
                if count.int1 == 1:
                    return ast_node.macro_expand(fn_symbol, words_needed, body,
                                                 kind='series')
                first_jmp = ()
            else:
                first_jmp = (
                    ast.ast(kind='jump', label=test, expect='statement'),
                )

            loop_var = crud.gensym('repeat_var')
            symbol_id = \
              symbol_table.symbol.create(loop_var, 'var', fn_symbol).id
            test = crud.gensym('repeat_test')
            new_args = (
              ast.ast(ast.ast.word(symbol_table.get('set').id),
                      (ast.ast.word(symbol_id),
                       count,
                      ),
                      kind='call',
                      expect='statement') \
                 .prepare(fn_symbol, words_needed),
            ) + first_jmp + (
              ast.ast(kind='label', label=loop_label, expect='statement'),
            ) + body + (
              ast.ast(ast.ast.word(symbol_table.get('set').id),
                      (ast.ast.word(symbol_id),
                       ast.ast(ast.ast.word(symbol_table.get('-').id),
                               ast.ast.word(symbol_id),
                               ast.ast(kind='int', int1=1),
                               kind='call',
                              ) \
                          .prepare(fn_symbol, words_needed),
                      ),
                      kind='call',
                      expect='statement') \
                 .prepare(fn_symbol, words_needed),
              ast.ast(kind='label', label=test, expect='statement'),
              ast.ast(ast.ast.word(symbol_id, expect='condition'),
                      kind='if-true',
                      label=loop_label,
                      expect='statement'),
            )

        return ast_node.macro_expand(fn_symbol, words_needed, new_args,
                                     kind='series')