"""
Tests coverign the VM interpreter
"""

from .fixtures import *  # noqa

from ichor import isa
from ichor.bootstrap import FALSE, TRUE
from ichor.interpreter import InterpreterError
import pytest


def test_return(vm):
    with pytest.raises(InterpreterError):
        vm.run([isa.RETURN()], stack=[])

    assert vm.run([isa.RETURN()], stack=[FALSE, TRUE]) == [FALSE]
    assert vm.run([isa.DROP(1), isa.RETURN()], stack=[TRUE, FALSE]) == [TRUE]


def test_dup(vm):
    assert vm.run([isa.DUP(1), isa.BREAK()], stack=[FALSE, TRUE]) == [FALSE, TRUE, TRUE]
    assert vm.run([isa.DUP(2), isa.BREAK()], stack=[FALSE, TRUE]) == [FALSE, TRUE, FALSE, TRUE]


def test_rot(vm):
    assert vm.run([
        isa.ROT(2),
        isa.BREAK()
    ], stack=[FALSE, TRUE]) == [TRUE, FALSE]

    assert vm.run([
        isa.ROT(2),
        isa.BREAK()
    ], stack=[TRUE, TRUE, TRUE, FALSE, TRUE]) == [TRUE, TRUE, TRUE, TRUE, FALSE]

    assert vm.run([
        isa.ROT(3),
        isa.BREAK()
    ], stack=[FALSE, TRUE, FALSE]) == [FALSE, FALSE, TRUE]


def test_drop(vm):
    assert vm.run([
        isa.DROP(1),
        isa.BREAK()
    ], stack=[TRUE, FALSE]) == [TRUE]


def test_dup_too_many(vm):
    with pytest.raises(InterpreterError):
        vm.run([isa.DUP(1)])

    with pytest.raises(InterpreterError):
        vm.run([isa.DUP(2)], stack=[FALSE])


def test_rot_too_many(vm):
    with pytest.raises(InterpreterError):
        vm.run([isa.ROT(1)])

    with pytest.raises(InterpreterError):
        vm.run([isa.ROT(2)], stack=[FALSE])


def test_drop_too_many(vm):
    with pytest.raises(InterpreterError):
        vm.run([isa.DROP(1)])

    with pytest.raises(InterpreterError):
        vm.run([isa.DROP(2)], stack=[FALSE])