Exemple #1
0
    def test_drop(self):
        m = forth.Machine()
        ret = m.eval('1 DROP')

        assert ret == ' ok'
        assert not m.data_stack

        m = forth.Machine()
        ret = m.eval('DROP')

        assert ret == ' ? stack underflow'
Exemple #2
0
    def test_tuck(self):
        m = forth.Machine()
        ret = m.eval('1 2 TUCK')

        assert ret == ' ok'
        assert m.data_stack == [2, 1, 2]

        m = forth.Machine()
        ret = m.eval('1 TUCK')

        assert ret == ' ? stack underflow'
Exemple #3
0
    def test_rot(self):
        m = forth.Machine()
        ret = m.eval('1 2 3 ROT')

        assert ret == ' ok'
        assert m.data_stack == [2, 3, 1]

        m = forth.Machine()
        ret = m.eval('1 2 ROT')

        assert ret == ' ? stack underflow'
Exemple #4
0
    def test_over(self):
        m = forth.Machine()
        ret = m.eval('1 2 OVER')

        assert ret == ' ok'
        assert m.data_stack == [1, 2, 1]

        m = forth.Machine()
        ret = m.eval('1 OVER')

        assert ret == ' ? stack underflow'
Exemple #5
0
    def test_dup(self):
        m = forth.Machine()
        ret = m.eval('9 DUP')

        assert ret == ' ok'
        assert m.data_stack == [9, 9]

        m = forth.Machine()
        ret = m.eval('DUP')

        assert ret == ' ? stack underflow'
Exemple #6
0
    def test_two_operand_underflow(self):
        for oper in ['+', '-', '*', '/', 'MOD', '/MOD', 'SWAP']:
            m = forth.Machine()
            ret = m.eval('1 ' + oper)

            assert ret == ' ? stack underflow'
            assert not m.data_stack
Exemple #7
0
    def test_bad_compile(self):
        m = forth.Machine()
        ret = m.eval(': STAR NO-SUCH-WORD')

        assert 'undefined word' in ret
        assert 'NO-SUCH-WORD' in ret
        assert m.mode is forth.IMMEDIATE_MODE
Exemple #8
0
    def test_multi_loop(self):
        m = forth.Machine()
        ret = m.eval(': CR 10 EMIT ;\n'
                     ': STAR 42 EMIT ;\n'
                     ': STARS 0 DO STAR LOOP ;\n'
                     ': STAR-LINES 0 DO 5 STARS CR LOOP ;\n'
                     '2 STAR-LINES')

        assert ret == '*****\n*****\n ok'

        m = forth.Machine()
        ret = m.eval(': CR 10 EMIT ;\n'
                     ': STAR-LINES 0 DO 5 0 DO 42 EMIT LOOP CR LOOP ;\n'
                     '2 STAR-LINES')

        assert ret == '*****\n*****\n ok'
Exemple #9
0
    def test_interpret(self):
        m = forth.Machine()
        ret = m.interpret([('NUMBER', 42), ('NUMBER', 30),
                           ('CALL', m.words['.'])])

        assert ret == '30 '
        assert m.data_stack == [42]
Exemple #10
0
    def test_quit(self):
        m = forth.Machine()
        ret = m.eval('4 QUIT 5')

        assert ret == ''
        assert 4 in m.data_stack
        assert 5 not in m.data_stack
Exemple #11
0
    def test_plus_loop(self):
        m = forth.Machine()

        assert 'missing DO' in m.eval(': OOPS +LOOP ;')
        assert 'underflow' in m.eval(': OOPS 2 0 DO 42 EMIT +LOOP ; OOPS')
        ret = m.eval(': JUMP-TWO DO 42 EMIT 2 +LOOP ; 4 0 JUMP-TWO')

        assert ret == '** ok'
Exemple #12
0
    def test_wrong_loop_close(self):
        m = forth.Machine()
        ret = m.eval(': BLAH')

        m.return_stack.append('OOPSIE')
        ret = m.eval('LOOP')

        assert 'unclosed OOPSIE' in ret
Exemple #13
0
    def test_printstack(self):
        m = forth.Machine()
        ret = m.eval('42 1 2 3 .S')

        assert m.data_stack == [42, 1, 2, 3]
        # Kind of a fragile test, as it relies on the implementation of .S
        # always including repr(self.data_stack), which it might not do in
        # future. Nonetheless, it's currently sufficiently correct.
        assert repr(m.data_stack) in ret
Exemple #14
0
def forth_repl():
    print('Type "BYE" or input an end of file (Ctrl+D) to quit.')

    m = forth.Machine()

    cmd = raw_input(PROMPT)
    while cmd.upper() != 'BYE':
        print(m.eval(cmd))
        cmd = raw_input(PROMPT)
Exemple #15
0
    def test_twin_operators(self):
        m = forth.Machine()
        ret = m.eval('10 7 2DUP')

        assert ret == ' ok'
        assert m.data_stack == [10, 7, 10, 7]

        m = forth.Machine()
        ret = m.eval('1 2 3 4 2SWAP')

        assert ret == ' ok'
        assert m.data_stack == [3, 4, 1, 2]

        m = forth.Machine()
        ret = m.eval('1 2 3 4 2OVER')

        assert ret == ' ok'
        assert m.data_stack == [1, 2, 3, 4, 1, 2]
Exemple #16
0
    def test_if_else_on_stack(self):
        m = forth.Machine()
        ret = m.eval(': TEST IF ELSE')

        assert 'compiled' in ret
        assert 'IF' in m.return_stack
        assert 'ELSE' in m.return_stack
        assert 'IF' in m.data_stack
        assert 'ELSE' in m.data_stack
Exemple #17
0
    def test_multi_eval(self):
        m = forth.Machine()
        ret = m.eval('12 34')

        assert ret == ' ok'
        assert m.data_stack == [12, 34]

        ret = m.eval('+')
        assert ret == ' ok'
        assert m.data_stack == [46]
Exemple #18
0
    def test_comparisons(self):
        m = forth.Machine()
        ret = m.eval('''10 7
                     2DUP > .
                     2DUP >= .
                     2DUP < .
                     2DUP <= .
                     2DUP == .
                     2DUP != .''')

        assert ret == '-1 -1 0 0 0 -1  ok'
Exemple #19
0
    def test_empty_if(self):
        m = forth.Machine()
        ret = m.eval(': TEST IF ELSE THEN ; 1 TEST')

        assert ret == ' ok'
        assert 'TEST' in m.words
        assert not m.data_stack
        assert not m.return_stack

        ret = m.eval(': TEST IF 42 EMIT THEN ; 1 TEST 0 TEST')
        assert ret == '* ok'
Exemple #20
0
    def test_if(self):
        m = forth.Machine()
        ret = m.eval(': TEST IF 42 ELSE 33 THEN . ;')

        assert ret == ' ok'
        assert 'TEST' in m.words
        assert not m.data_stack
        assert not m.return_stack

        assert m.eval('1 TEST 0 TEST') == '42 33  ok'
        assert 'stack underflow' in m.eval('TEST')
Exemple #21
0
    def test_error_clears_stack(self):
        m = forth.Machine()
        ret = m.eval('42')

        assert ret == ' ok'
        assert m.data_stack == [42]

        ret = m.eval('NO-SUCH-WORD')

        assert 'undefined word' in ret
        assert not m.data_stack
Exemple #22
0
    def test_simple_math(self):
        for oper, expected in {
                '+': 24,
                '-': 16,
                '*': 80,
                '/': 5,
                'MOD': 0
        }.iteritems():
            m = forth.Machine()
            ret = m.eval('20 4 ' + oper)

            assert ret == ' ok'
            assert expected in m.data_stack
Exemple #23
0
    def test_complete_compile(self):
        m = forth.Machine()
        ret = m.eval(': STAR 42 EMIT ;')

        assert 'ok' in ret
        assert 'STAR' in m.words
        assert m.data_stack == []
        assert m.mode is forth.IMMEDIATE_MODE

        ret = m.eval('STAR')

        assert ret == '* ok'
        assert m.data_stack == []
Exemple #24
0
    def test_begin_until(self):
        m = forth.Machine()
        assert 'compile-only' in m.eval('BEGIN')
        assert 'compile-only' in m.eval('UNTIL')
        assert 'missing BEGIN' in m.eval(': TEST UNTIL')
        assert 'unclosed DO' in m.eval(': TEST DO UNTIL')

        ret = m.eval(''': TEST 0
                     BEGIN
                        DUP .
                        1 +
                        DUP
                     4 > UNTIL
                     ; TEST''')

        assert ret == '0 1 2 3 4  ok'
Exemple #25
0
    def test_leave(self):
        m = forth.Machine()
        assert 'compile-only' in m.eval('LEAVE')
        assert '? not looping' in m.eval(': TEST LEAVE ; TEST')

        ret = m.eval(''': TEST
                     10 5
                     2 0 DO
                        DUP
                        7 > IF
                            LEAVE
                        THEN
                        .
                     LOOP ;
                     TEST''')

        assert ret == '5  ok'
Exemple #26
0
    def test_return_stack_fuckery(self):
        m = forth.Machine()
        ret = m.eval('1 2 3 >R SWAP R>  . . .')

        assert ret == '3 1 2  ok'
        assert not m.data_stack

        assert m.eval('2 >R R@ R> . .') == '2 2  ok'

        assert not m.return_stack
        assert 'return stack underflow' in m.eval('R>')

        assert m.eval(': TEST 5 0 DO I . LOOP ; TEST') == '0 1 2 3 4  ok'
        assert m.eval(': TEST 5 0 DO R> . 5 >R LOOP ; TEST') == '0  ok'

        ret = m.eval(
            ': TEST 12 10 DO 22 20 DO 42 EMIT J . I . LOOP LOOP ; TEST')
        assert ret == '*10 20 *10 21 *11 20 *11 21  ok'
Exemple #27
0
    def test_begin_while_repeat(self):
        m = forth.Machine()
        assert 'compile-only' in m.eval('BEGIN')
        assert 'compile-only' in m.eval('WHILE')
        assert 'compile-only' in m.eval('REPEAT')
        assert 'missing BEGIN' in m.eval(': TEST WHILE')
        assert 'missing WHILE' in m.eval(': TEST REPEAT')
        assert 'unclosed DO' in m.eval(': TEST DO WHILE')
        assert 'unclosed DO' in m.eval(': TEST DO REPEAT')

        ret = m.eval(''': TEST 0
                     BEGIN
                        DUP
                     4 < WHILE
                        DUP .
                        1 +
                     REPEAT
                     ; TEST''')

        assert ret == '0 1 2 3  ok'
Exemple #28
0
    def test_two_part_compile(self):
        m = forth.Machine()
        ret = m.eval(': STAR')
        ret = m.eval('42 EMIT')

        assert ret == ' compiled'
        assert ':' in m.data_stack
        assert m.return_stack == [':']
        assert m.mode is forth.COMPILE_MODE
        assert 'STAR' not in m.words

        ret = m.eval(';')
        assert ret == ' ok'
        assert m.data_stack == []
        assert not m.return_stack
        assert m.mode is forth.IMMEDIATE_MODE
        assert 'STAR' in m.words

        ret = m.eval('STAR STAR')

        assert ret == '** ok'
        assert m.data_stack == []
Exemple #29
0
    def test_swap(self):
        m = forth.Machine()
        ret = m.eval('5 12 SWAP')

        assert ret == ' ok'
        assert m.data_stack == [12, 5]
Exemple #30
0
    def test_divmod(self):
        m = forth.Machine()
        ret = m.eval('17 3 /MOD')

        assert ret == ' ok'
        assert m.data_stack == [2, 5]