Beispiel #1
0
def test_optimize_single_block():
    slot1 = pt.ScratchSlot(1)
    slot2 = pt.ScratchSlot(2)

    # empty check
    empty_block = pt.TealSimpleBlock([])
    _apply_slot_to_stack(empty_block, empty_block, {})

    expected = pt.TealSimpleBlock([])
    assert empty_block == expected

    # basic optimization
    block = pt.TealSimpleBlock([
        pt.TealOp(None, pt.Op.store, slot1),
        pt.TealOp(None, pt.Op.load, slot1),
    ])
    _apply_slot_to_stack(block, block, {})

    expected = pt.TealSimpleBlock([])
    assert block == expected

    # iterate optimization
    block = pt.TealSimpleBlock([
        pt.TealOp(None, pt.Op.store, slot1),
        pt.TealOp(None, pt.Op.store, slot2),
        pt.TealOp(None, pt.Op.load, slot2),
        pt.TealOp(None, pt.Op.load, slot1),
    ])
    _apply_slot_to_stack(block, block, {})

    expected = pt.TealSimpleBlock([
        pt.TealOp(None, pt.Op.store, slot1),
        pt.TealOp(None, pt.Op.load, slot1),
    ])
    assert block == expected

    _apply_slot_to_stack(block, block, {})
    expected = pt.TealSimpleBlock([])
    assert block == expected

    # remove extraneous stores
    block = pt.TealSimpleBlock([
        pt.TealOp(None, pt.Op.store, slot1),
        pt.TealOp(None, pt.Op.load, slot1),
        pt.TealOp(None, pt.Op.store, slot1),
    ])
    _apply_slot_to_stack(block, block, {})

    expected = pt.TealSimpleBlock([])
    assert block == expected
Beispiel #2
0
def test_GetReferencedScratchSlots():
    a = pt.ScratchSlot()
    b = pt.ScratchSlot()
    c = pt.ScratchSlot()
    d = pt.ScratchSlot()

    end = pt.TealSimpleBlock([pt.TealOp(None, pt.Op.load, d)])
    trueBranch = pt.TealSimpleBlock([pt.TealOp(None, pt.Op.load, b)])
    trueBranch.setNextBlock(end)
    falseBranch = pt.TealSimpleBlock([pt.TealOp(None, pt.Op.load, c)])
    falseBranch.setNextBlock(end)
    splitBranch = pt.TealConditionalBlock([pt.TealOp(None, pt.Op.load, a)])
    splitBranch.setTrueBlock(trueBranch)
    splitBranch.setFalseBlock(falseBranch)

    slotReferences = pt.TealBlock.GetReferencedScratchSlots(splitBranch)
    assert slotReferences == [a, b, c, d]
Beispiel #3
0
def test_scratch_load_default():
    slot = pt.ScratchSlot()
    expr = pt.ScratchLoad(slot)
    assert expr.type_of() == pt.TealType.anytype

    expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.load, slot)])

    actual, _ = expr.__teal__(options)

    assert actual == expected
Beispiel #4
0
def test_scratch_assign_id():
    slot = pt.ScratchSlot(255)
    expr = pt.ScratchStackStore(slot)
    assert expr.type_of() == pt.TealType.none

    expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.store, slot)])

    actual, _ = expr.__teal__(options)

    assert actual == expected
Beispiel #5
0
def test_scratch_load_type():
    for type in (pt.TealType.uint64, pt.TealType.bytes, pt.TealType.anytype):
        slot = pt.ScratchSlot()
        expr = pt.ScratchLoad(slot, type)
        assert expr.type_of() == type

        expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.load, slot)])

        actual, _ = expr.__teal__(options)

        assert actual == expected
Beispiel #6
0
def test_scratch_slot():
    slot = pt.ScratchSlot()
    assert slot == slot
    assert slot.__hash__() == slot.__hash__()
    assert slot != pt.ScratchSlot()

    with pt.TealComponent.Context.ignoreExprEquality():
        assert (
            slot.store().__teal__(options)[0]
            == pt.ScratchStackStore(slot).__teal__(options)[0]
        )
        assert (
            slot.store(pt.Int(1)).__teal__(options)[0]
            == pt.ScratchStore(slot, pt.Int(1)).__teal__(options)[0]
        )

        assert slot.load().type_of() == pt.TealType.anytype
        assert slot.load(pt.TealType.uint64).type_of() == pt.TealType.uint64
        assert (
            slot.load().__teal__(options)[0]
            == pt.ScratchLoad(slot).__teal__(options)[0]
        )
Beispiel #7
0
def test_assignScratchSlotsToSubroutines_slot_used_before_assignment():
    def sub1Impl():
        return None

    def sub2Impl(a1):
        return None

    def sub3Impl(a1, a2, a3):
        return None

    subroutine1 = pt.SubroutineDefinition(sub1Impl, pt.TealType.uint64)
    subroutine2 = pt.SubroutineDefinition(sub2Impl, pt.TealType.bytes)
    subroutine3 = pt.SubroutineDefinition(sub3Impl, pt.TealType.none)

    globalSlot1 = pt.ScratchSlot()

    subroutine1Slot1 = pt.ScratchSlot()
    subroutine1Slot2 = pt.ScratchSlot()
    subroutine1Ops = [
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, subroutine1Slot1),
        pt.TealOp(None, pt.Op.int, 3),
        pt.TealOp(None, pt.Op.store, subroutine1Slot2),
        pt.TealOp(None, pt.Op.load, globalSlot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine2Slot1 = pt.ScratchSlot()
    subroutine2Ops = [
        pt.TealOp(None, pt.Op.byte, '"value"'),
        pt.TealOp(None, pt.Op.store, subroutine2Slot1),
        pt.TealOp(None, pt.Op.load, subroutine2Slot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine3Ops = [
        pt.TealOp(None, pt.Op.retsub),
    ]

    mainSlot1 = pt.ScratchSlot()
    mainSlot2 = pt.ScratchSlot()
    mainOps = [
        pt.TealOp(None, pt.Op.int, 7),
        pt.TealOp(None, pt.Op.store, globalSlot1),
        pt.TealOp(None, pt.Op.int, 2),
        pt.TealOp(None, pt.Op.store, mainSlot2),
        pt.TealOp(None, pt.Op.load, mainSlot1),
        pt.TealOp(None, pt.Op.return_),
    ]

    subroutineBlocks = {
        None: pt.TealSimpleBlock(mainOps),
        subroutine1: pt.TealSimpleBlock(subroutine1Ops),
        subroutine2: pt.TealSimpleBlock(subroutine2Ops),
        subroutine3: pt.TealSimpleBlock(subroutine3Ops),
    }

    with pytest.raises(pt.TealInternalError):
        assignScratchSlotsToSubroutines(subroutineBlocks)
Beispiel #8
0
def test_scratch_index():
    slot = pt.ScratchSlot()

    index = pt.ScratchIndex(slot)
    assert index.slot is slot

    assert str(index) == "(ScratchIndex " + str(slot) + ")"

    assert index.type_of() == pt.TealType.uint64

    assert not index.has_return()

    expected = pt.TealSimpleBlock([pt.TealOp(index, pt.Op.int, slot)])
    actual, _ = index.__teal__(options)

    assert actual == expected
Beispiel #9
0
def test_scratch_store():
    for value in (
        pt.Int(1),
        pt.Bytes("test"),
        pt.App.globalGet(pt.Bytes("key")),
        pt.If(pt.Int(1), pt.Int(2), pt.Int(3)),
    ):
        slot = pt.ScratchSlot()
        expr = pt.ScratchStore(slot, value)
        assert expr.type_of() == pt.TealType.none

        expected, valueEnd = value.__teal__(options)
        storeBlock = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.store, slot)])
        valueEnd.setNextBlock(storeBlock)

        actual, _ = expr.__teal__(options)

        assert actual == expected
Beispiel #10
0
def test_scratch_assign_id_invalid():
    with pytest.raises(pt.TealInputError):
        pt.ScratchSlot(-1)

    with pytest.raises(pt.TealInputError):
        pt.ScratchSlot(pt.NUM_SLOTS)
Beispiel #11
0
def test_MatchScratchSlotReferences():
    class MatchSlotReferenceTest(NamedTuple):
        actual: List[pt.ScratchSlot]
        expected: List[pt.ScratchSlot]
        match: bool

    a = pt.ScratchSlot()
    b = pt.ScratchSlot()
    c = pt.ScratchSlot()
    d = pt.ScratchSlot()

    tests: List[MatchSlotReferenceTest] = [
        MatchSlotReferenceTest(
            actual=[],
            expected=[],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a],
            expected=[],
            match=False,
        ),
        MatchSlotReferenceTest(
            actual=[a],
            expected=[a],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a],
            expected=[b],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, a],
            expected=[a, a],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, a],
            expected=[b, b],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, b],
            expected=[a, b],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, b],
            expected=[b, c],
            match=False,
        ),
        MatchSlotReferenceTest(
            actual=[a, b],
            expected=[c, d],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, b, b, a, b],
            expected=[c, d, d, c, d],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, b, b, a, b],
            expected=[a, d, d, a, d],
            match=True,
        ),
        MatchSlotReferenceTest(
            actual=[a, b, b, a, b],
            expected=[c, a, a, c, a],
            match=False,
        ),
        MatchSlotReferenceTest(
            actual=[a, b, b, a, b],
            expected=[c, d, d, c, c],
            match=False,
        ),
    ]

    for i, test in enumerate(tests):
        assert (pt.TealBlock.MatchScratchSlotReferences(
            test.actual,
            test.expected) == test.match), "Test at index {} failed".format(i)
Beispiel #12
0
def test_assignScratchSlotsToSubroutines_no_requested_ids():
    def sub1Impl():
        return None

    def sub2Impl(a1):
        return None

    def sub3Impl(a1, a2, a3):
        return None

    subroutine1 = pt.SubroutineDefinition(sub1Impl, pt.TealType.uint64)
    subroutine2 = pt.SubroutineDefinition(sub2Impl, pt.TealType.bytes)
    subroutine3 = pt.SubroutineDefinition(sub3Impl, pt.TealType.none)

    globalSlot1 = pt.ScratchSlot()

    subroutine1Slot1 = pt.ScratchSlot()
    subroutine1Slot2 = pt.ScratchSlot()
    subroutine1Ops = [
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, subroutine1Slot1),
        pt.TealOp(None, pt.Op.int, 3),
        pt.TealOp(None, pt.Op.store, subroutine1Slot2),
        pt.TealOp(None, pt.Op.load, globalSlot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine2Slot1 = pt.ScratchSlot()
    subroutine2Ops = [
        pt.TealOp(None, pt.Op.byte, '"value"'),
        pt.TealOp(None, pt.Op.store, subroutine2Slot1),
        pt.TealOp(None, pt.Op.load, subroutine2Slot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine3Ops = [
        pt.TealOp(None, pt.Op.retsub),
    ]

    mainSlot1 = pt.ScratchSlot()
    mainSlot2 = pt.ScratchSlot()
    mainOps = [
        pt.TealOp(None, pt.Op.int, 7),
        pt.TealOp(None, pt.Op.store, globalSlot1),
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, mainSlot1),
        pt.TealOp(None, pt.Op.int, 2),
        pt.TealOp(None, pt.Op.store, mainSlot2),
        pt.TealOp(None, pt.Op.load, mainSlot1),
        pt.TealOp(None, pt.Op.return_),
    ]

    subroutineBlocks = {
        None: pt.TealSimpleBlock(mainOps),
        subroutine1: pt.TealSimpleBlock(subroutine1Ops),
        subroutine2: pt.TealSimpleBlock(subroutine2Ops),
        subroutine3: pt.TealSimpleBlock(subroutine3Ops),
    }

    expectedAssignments = {
        globalSlot1: 0,
        subroutine1Slot1: 1,
        subroutine1Slot2: 2,
        subroutine2Slot1: 3,
        mainSlot1: 4,
        mainSlot2: 5,
    }

    expected = {
        None: {expectedAssignments[mainSlot1], expectedAssignments[mainSlot2]},
        subroutine1: {
            expectedAssignments[subroutine1Slot1],
            expectedAssignments[subroutine1Slot2],
        },
        subroutine2: {expectedAssignments[subroutine2Slot1]},
        subroutine3: set(),
    }

    actual = assignScratchSlotsToSubroutines(subroutineBlocks)

    assert actual == expected

    assert subroutine1Ops == [
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, expectedAssignments[subroutine1Slot1]),
        pt.TealOp(None, pt.Op.int, 3),
        pt.TealOp(None, pt.Op.store, expectedAssignments[subroutine1Slot2]),
        pt.TealOp(None, pt.Op.load, expectedAssignments[globalSlot1]),
        pt.TealOp(None, pt.Op.retsub),
    ]

    assert subroutine2Ops == [
        pt.TealOp(None, pt.Op.byte, '"value"'),
        pt.TealOp(None, pt.Op.store, expectedAssignments[subroutine2Slot1]),
        pt.TealOp(None, pt.Op.load, expectedAssignments[subroutine2Slot1]),
        pt.TealOp(None, pt.Op.retsub),
    ]

    assert subroutine3Ops == [
        pt.TealOp(None, pt.Op.retsub),
    ]

    assert mainOps == [
        pt.TealOp(None, pt.Op.int, 7),
        pt.TealOp(None, pt.Op.store, expectedAssignments[globalSlot1]),
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, expectedAssignments[mainSlot1]),
        pt.TealOp(None, pt.Op.int, 2),
        pt.TealOp(None, pt.Op.store, expectedAssignments[mainSlot2]),
        pt.TealOp(None, pt.Op.load, expectedAssignments[mainSlot1]),
        pt.TealOp(None, pt.Op.return_),
    ]
Beispiel #13
0
def test_assignScratchSlotsToSubroutines_invalid_requested_id():
    def sub1Impl():
        return None

    def sub2Impl(a1):
        return None

    def sub3Impl(a1, a2, a3):
        return None

    subroutine1 = pt.SubroutineDefinition(sub1Impl, pt.TealType.uint64)
    subroutine2 = pt.SubroutineDefinition(sub2Impl, pt.TealType.bytes)
    subroutine3 = pt.SubroutineDefinition(sub3Impl, pt.TealType.none)

    globalSlot1 = pt.ScratchSlot(requestedSlotId=8)

    subroutine1Slot1 = pt.ScratchSlot()
    subroutine1Slot2 = pt.ScratchSlot(requestedSlotId=5)
    subroutine1Ops = [
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, subroutine1Slot1),
        pt.TealOp(None, pt.Op.int, 3),
        pt.TealOp(None, pt.Op.store, subroutine1Slot2),
        pt.TealOp(None, pt.Op.load, globalSlot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine2Slot1 = pt.ScratchSlot(requestedSlotId=100)
    subroutine2Ops = [
        pt.TealOp(None, pt.Op.byte, '"value"'),
        pt.TealOp(None, pt.Op.store, subroutine2Slot1),
        pt.TealOp(None, pt.Op.load, subroutine2Slot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine3Ops = [
        pt.TealOp(None, pt.Op.retsub),
    ]

    mainSlot1 = pt.ScratchSlot()
    mainSlot2 = pt.ScratchSlot(requestedSlotId=100)
    mainOps = [
        pt.TealOp(None, pt.Op.int, 7),
        pt.TealOp(None, pt.Op.store, globalSlot1),
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, mainSlot1),
        pt.TealOp(None, pt.Op.int, 2),
        pt.TealOp(None, pt.Op.store, mainSlot2),
        pt.TealOp(None, pt.Op.load, mainSlot1),
        pt.TealOp(None, pt.Op.return_),
    ]

    subroutineBlocks = {
        None: pt.TealSimpleBlock(mainOps),
        subroutine1: pt.TealSimpleBlock(subroutine1Ops),
        subroutine2: pt.TealSimpleBlock(subroutine2Ops),
        subroutine3: pt.TealSimpleBlock(subroutine3Ops),
    }

    # mainSlot2 and subroutine2Slot1 request the same ID, 100
    with pytest.raises(pt.TealInternalError):
        assignScratchSlotsToSubroutines(subroutineBlocks)
Beispiel #14
0
def test_collectScratchSlots():
    def sub1Impl():
        return None

    def sub2Impl(a1):
        return None

    def sub3Impl(a1, a2, a3):
        return None

    subroutine1 = pt.SubroutineDefinition(sub1Impl, pt.TealType.uint64)
    subroutine2 = pt.SubroutineDefinition(sub2Impl, pt.TealType.bytes)
    subroutine3 = pt.SubroutineDefinition(sub3Impl, pt.TealType.none)

    globalSlot1 = pt.ScratchSlot()

    subroutine1Slot1 = pt.ScratchSlot()
    subroutine1Slot2 = pt.ScratchSlot()
    subroutine1Ops = [
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, subroutine1Slot1),
        pt.TealOp(None, pt.Op.int, 3),
        pt.TealOp(None, pt.Op.store, subroutine1Slot2),
        pt.TealOp(None, pt.Op.load, globalSlot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine2Slot1 = pt.ScratchSlot()
    subroutine2Ops = [
        pt.TealOp(None, pt.Op.byte, '"value"'),
        pt.TealOp(None, pt.Op.store, subroutine2Slot1),
        pt.TealOp(None, pt.Op.load, subroutine2Slot1),
        pt.TealOp(None, pt.Op.retsub),
    ]

    subroutine3Ops = [
        pt.TealOp(None, pt.Op.retsub),
    ]

    mainSlot1 = pt.ScratchSlot()
    mainSlot2 = pt.ScratchSlot()
    mainOps = [
        pt.TealOp(None, pt.Op.int, 7),
        pt.TealOp(None, pt.Op.store, globalSlot1),
        pt.TealOp(None, pt.Op.int, 1),
        pt.TealOp(None, pt.Op.store, mainSlot1),
        pt.TealOp(None, pt.Op.int, 2),
        pt.TealOp(None, pt.Op.store, mainSlot2),
        pt.TealOp(None, pt.Op.load, mainSlot1),
        pt.TealOp(None, pt.Op.return_),
    ]

    subroutineBlocks = {
        None: pt.TealSimpleBlock(mainOps),
        subroutine1: pt.TealSimpleBlock(subroutine1Ops),
        subroutine2: pt.TealSimpleBlock(subroutine2Ops),
        subroutine3: pt.TealSimpleBlock(subroutine3Ops),
    }

    expected_global = {globalSlot1}

    expected_local = {
        None: {mainSlot1, mainSlot2},
        subroutine1: {subroutine1Slot1, subroutine1Slot2},
        subroutine2: {subroutine2Slot1},
        subroutine3: set(),
    }

    actual_global, actual_local = collectScratchSlots(subroutineBlocks)

    assert actual_global == expected_global
    assert actual_local == expected_local