using Test
include("/home/allaun/SilverSight/julia/CoreFormalism/Q16_16.jl")
include("/home/allaun/SilverSight/julia/AVMIsa/avm.jl")
using .Q16_16
using .AVM

@testset "AVM ISA" begin

    @testset "add Q16" begin
        prog = [
            AVM.push_q16(5 * 65536),
            AVM.push_q16(3 * 65536),
            AVM.prim(AVM.ADD_SAT_Q16),
            AVM.halt(),
        ]
        state = AVM.State(0)
        final = AVM.run(state, prog, 100)
        @test final.halted
        @test length(final.stack) == 1
        @test AVM.q16_val(final, 1) == 8 * 65536
        @test final.pc == 5
    end

    @testset "jump_if" begin
        prog = [
            AVM.push_val(true),
            AVM.jump_if(4),
            AVM.push_q16(0),
            AVM.halt(),
            AVM.push_q16(65536),
            AVM.halt(),
        ]
        state = AVM.State(0)
        final = AVM.run(state, prog, 100)
        @test final.halted
        @test length(final.stack) == 1
        @test AVM.q16_val(final, 1) == 65536
        @test final.pc == 7   # after halt at position 6, pc → 7
    end

    @testset "store_load" begin
        prog = [
            AVM.push_q16(42 * 65536),
            AVM.store(0),
            AVM.load(0),
            AVM.halt(),
        ]
        state = AVM.State(1)
        final = AVM.run(state, prog, 100)
        @test length(final.stack) == 1
        @test AVM.q16_val(final, 1) == 42 * 65536
    end

    @testset "type error" begin
        prog = [
            AVM.push_val(true),
            AVM.push_q16(65536),
            AVM.prim(AVM.ADD_SAT_Q16),
            AVM.halt(),
        ]
        state = AVM.State(0)
        @test_throws Exception AVM.run(state, prog, 100)
    end

    @testset "division by zero" begin
        prog = [
            AVM.push_q16(65536),
            AVM.push_q16(0),
            AVM.prim(AVM.DIV_SAT_Q16),
            AVM.halt(),
        ]
        state = AVM.State(0)
        @test_throws Exception AVM.run(state, prog, 100)
    end

end
