Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add error for scratch slot load before store #47

Merged
merged 1 commit into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions pyteal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from .ir import __all__ as ir_all
from .compiler import compileTeal
from .types import TealType
from .errors import TealInternalError, TealTypeError, TealInputError
from .util import execute
from .errors import TealInternalError, TealTypeError, TealInputError, TealCompileError
from .config import MAX_GROUP_SIZE

__all__ = ast_all + ir_all + [
Expand All @@ -14,6 +13,6 @@
"TealInternalError",
"TealTypeError",
"TealInputError",
"execute",
"TealCompileError",
"MAX_GROUP_SIZE",
]
3 changes: 2 additions & 1 deletion pyteal/ast/addr.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ def __init__(self, address: str) -> None:
Args:
address: A string containing a valid base32 Algorand address
"""
super().__init__()
valid_address(address)
self.address = address

def __teal__(self):
op = TealOp(Op.addr, self.address)
op = TealOp(self, Op.addr, self.address)
return TealBlock.FromOp(op)

def __str__(self):
Expand Down
2 changes: 1 addition & 1 deletion pyteal/ast/addr_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def test_addr():
expr = Addr("NJUWK3DJNZTWU2LFNRUW4Z3KNFSWY2LOM5VGSZLMNFXGO2TJMVWGS3THMF")
assert expr.type_of() == TealType.bytes
expected = TealSimpleBlock([
TealOp(Op.addr, "NJUWK3DJNZTWU2LFNRUW4Z3KNFSWY2LOM5VGSZLMNFXGO2TJMVWGS3THMF")
TealOp(expr, Op.addr, "NJUWK3DJNZTWU2LFNRUW4Z3KNFSWY2LOM5VGSZLMNFXGO2TJMVWGS3THMF")
])
actual, _ = expr.__teal__()
assert actual == expected
Expand Down
3 changes: 2 additions & 1 deletion pyteal/ast/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class App(LeafExpr):
"""An expression related to applications."""

def __init__(self, field:AppField, args) -> None:
super().__init__()
self.field = field
self.args = args

Expand All @@ -58,7 +59,7 @@ def __str__(self):
return ret_str

def __teal__(self):
return TealBlock.FromOp(TealOp(self.field.get_op()), *self.args)
return TealBlock.FromOp(TealOp(self, self.field.get_op()), *self.args)

def type_of(self):
return self.field.type_of()
Expand Down
110 changes: 61 additions & 49 deletions pyteal/ast/app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,44 @@

def test_on_complete():
assert OnComplete.NoOp.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "NoOp")
TealOp(OnComplete.NoOp, Op.int, "NoOp")
])

assert OnComplete.OptIn.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "OptIn")
TealOp(OnComplete.OptIn, Op.int, "OptIn")
])

assert OnComplete.CloseOut.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "CloseOut")
TealOp(OnComplete.CloseOut, Op.int, "CloseOut")
])

assert OnComplete.ClearState.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "ClearState")
TealOp(OnComplete.ClearState, Op.int, "ClearState")
])

assert OnComplete.UpdateApplication.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "UpdateApplication")
TealOp(OnComplete.UpdateApplication, Op.int, "UpdateApplication")
])

assert OnComplete.DeleteApplication.__teal__()[0] == TealSimpleBlock([
TealOp(Op.int, "DeleteApplication")
TealOp(OnComplete.DeleteApplication, Op.int, "DeleteApplication")
])

def test_app_id():
expr = App.id()
assert expr.type_of() == TealType.uint64
assert expr.__teal__()[0] == Global.current_application_id().__teal__()[0]
with TealComponent.Context.ignoreExprEquality():
assert expr.__teal__()[0] == Global.current_application_id().__teal__()[0]

def test_opted_in():
expr = App.optedIn(Int(1), Int(12))
args = [Int(1), Int(12)]
expr = App.optedIn(args[0], args[1])
assert expr.type_of() == TealType.uint64

expected = TealSimpleBlock([
TealOp(Op.int, 1),
TealOp(Op.int, 12),
TealOp(Op.app_opted_in)
TealOp(args[0], Op.int, 1),
TealOp(args[1], Op.int, 12),
TealOp(expr, Op.app_opted_in)
])

actual, _ = expr.__teal__()
Expand All @@ -49,13 +51,14 @@ def test_opted_in():
assert actual == expected

def test_local_get():
expr = App.localGet(Int(0), Bytes("key"))
args = [Int(0), Bytes("key")]
expr = App.localGet(args[0], args[1])
assert expr.type_of() == TealType.anytype

expected = TealSimpleBlock([
TealOp(Op.int, 0),
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_local_get)
TealOp(args[0], Op.int, 0),
TealOp(args[1], Op.byte, "\"key\""),
TealOp(expr, Op.app_local_get)
])

actual, _ = expr.__teal__()
Expand All @@ -72,24 +75,26 @@ def test_local_get_invalid():
App.localGet(Int(0), Int(1))

def test_local_get_ex():
expr = App.localGetEx(Int(0), Int(6), Bytes("key"))
args = [Int(0), Int(6), Bytes("key")]
expr = App.localGetEx(args[0], args[1], args[2])
assert expr.type_of() == TealType.none
assert expr.value().type_of() == TealType.anytype

expected = TealSimpleBlock([
TealOp(Op.int, 0),
TealOp(Op.int, 6),
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_local_get_ex),
TealOp(Op.store, expr.slotOk),
TealOp(Op.store, expr.slotValue)
TealOp(args[0], Op.int, 0),
TealOp(args[1], Op.int, 6),
TealOp(args[2], Op.byte, "\"key\""),
TealOp(expr, Op.app_local_get_ex),
TealOp(None, Op.store, expr.slotOk),
TealOp(None, Op.store, expr.slotValue)
])

actual, _ = expr.__teal__()
actual.addIncoming()
actual = TealBlock.NormalizeBlocks(actual)

assert actual == expected
with TealComponent.Context.ignoreExprEquality():
assert actual == expected

def test_local_get_ex_invalid():
with pytest.raises(TealTypeError):
Expand All @@ -102,12 +107,13 @@ def test_local_get_ex_invalid():
App.localGetEx(Int(0), Int(0), Int(1))

def test_global_get():
expr = App.globalGet(Bytes("key"))
arg = Bytes("key")
expr = App.globalGet(arg)
assert expr.type_of() == TealType.anytype

expected = TealSimpleBlock([
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_global_get)
TealOp(arg, Op.byte, "\"key\""),
TealOp(expr, Op.app_global_get)
])

actual, _ = expr.__teal__()
Expand All @@ -121,23 +127,25 @@ def test_global_get_invalid():
App.globalGet(Int(7))

def test_global_get_ex():
expr = App.globalGetEx(Int(6), Bytes("key"))
args = [Int(6), Bytes("key")]
expr = App.globalGetEx(args[0], args[1])
assert expr.type_of() == TealType.none
assert expr.value().type_of() == TealType.anytype

expected = TealSimpleBlock([
TealOp(Op.int, 6),
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_global_get_ex),
TealOp(Op.store, expr.slotOk),
TealOp(Op.store, expr.slotValue)
TealOp(args[0], Op.int, 6),
TealOp(args[1], Op.byte, "\"key\""),
TealOp(expr, Op.app_global_get_ex),
TealOp(None, Op.store, expr.slotOk),
TealOp(None, Op.store, expr.slotValue)
])

actual, _ = expr.__teal__()
actual.addIncoming()
actual = TealBlock.NormalizeBlocks(actual)

assert actual == expected
with TealComponent.Context.ignoreExprEquality():
assert actual == expected

def test_global_get_ex_invalid():
with pytest.raises(TealTypeError):
Expand All @@ -147,14 +155,15 @@ def test_global_get_ex_invalid():
App.globalGetEx(Int(0), Int(1))

def test_local_put():
expr = App.localPut(Int(0), Bytes("key"), Int(5))
args = [Int(0), Bytes("key"), Int(5)]
expr = App.localPut(args[0], args[1], args[2])
assert expr.type_of() == TealType.none

expected = TealSimpleBlock([
TealOp(Op.int, 0),
TealOp(Op.byte, "\"key\""),
TealOp(Op.int, 5),
TealOp(Op.app_local_put)
TealOp(args[0], Op.int, 0),
TealOp(args[1], Op.byte, "\"key\""),
TealOp(args[2], Op.int, 5),
TealOp(expr, Op.app_local_put)
])

actual, _ = expr.__teal__()
Expand All @@ -174,13 +183,14 @@ def test_local_put_invalid():
App.localPut(Int(1), Bytes("key"), Pop(Int(1)))

def test_global_put():
expr = App.globalPut(Bytes("key"), Int(5))
args = [Bytes("key"), Int(5)]
expr = App.globalPut(args[0], args[1])
assert expr.type_of() == TealType.none

expected = TealSimpleBlock([
TealOp(Op.byte, "\"key\""),
TealOp(Op.int, 5),
TealOp(Op.app_global_put)
TealOp(args[0], Op.byte, "\"key\""),
TealOp(args[1], Op.int, 5),
TealOp(expr, Op.app_global_put)
])

actual, _ = expr.__teal__()
Expand All @@ -197,13 +207,14 @@ def test_global_put_invalid():
App.globalPut(Bytes("key"), Pop(Int(1)))

def test_local_del():
expr = App.localDel(Int(0), Bytes("key"))
args = [Int(0), Bytes("key")]
expr = App.localDel(args[0], args[1])
assert expr.type_of() == TealType.none

expected = TealSimpleBlock([
TealOp(Op.int, 0),
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_local_del)
TealOp(args[0], Op.int, 0),
TealOp(args[1], Op.byte, "\"key\""),
TealOp(expr, Op.app_local_del)
])

actual, _ = expr.__teal__()
Expand All @@ -220,12 +231,13 @@ def test_local_del_invalid():
App.localDel(Int(1), Int(2))

def test_global_del():
expr = App.globalDel(Bytes("key"))
arg = Bytes("key")
expr = App.globalDel(arg)
assert expr.type_of() == TealType.none

expected = TealSimpleBlock([
TealOp(Op.byte, "\"key\""),
TealOp(Op.app_global_del)
TealOp(arg, Op.byte, "\"key\""),
TealOp(expr, Op.app_global_del)
])

actual, _ = expr.__teal__()
Expand Down
4 changes: 3 additions & 1 deletion pyteal/ast/arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def __init__(self, index: int) -> None:
Args:
index: The integer index of the argument to get. Must be between 0 and 255 inclusive.
"""
super().__init__()

if type(index) is not int:
raise TealInputError("invalid arg input type {}".format(type(index)))

Expand All @@ -24,7 +26,7 @@ def __init__(self, index: int) -> None:
self.index = index

def __teal__(self):
op = TealOp(Op.arg, self.index)
op = TealOp(self, Op.arg, self.index)
return TealBlock.FromOp(op)

def __str__(self):
Expand Down
2 changes: 1 addition & 1 deletion pyteal/ast/arg_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def test_arg():
expr = Arg(0)
assert expr.type_of() == TealType.bytes
expected = TealSimpleBlock([
TealOp(Op.arg, 0)
TealOp(expr, Op.arg, 0)
])
actual, _ = expr.__teal__()
assert actual == expected
Expand Down
4 changes: 2 additions & 2 deletions pyteal/ast/assert_.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ..types import TealType, require_type
from ..ir import TealOp, Op, TealSimpleBlock, TealConditionalBlock
from ..util import new_label
from .expr import Expr

class Assert(Expr):
Expand All @@ -12,14 +11,15 @@ def __init__(self, cond: Expr) -> None:
Args:
cond: The condition to check. Must evaluate to a uint64.
"""
super().__init__()
require_type(cond.type_of(), TealType.uint64)
self.cond = cond

def __teal__(self):
condStart, condEnd = self.cond.__teal__()

end = TealSimpleBlock([])
errBlock = TealSimpleBlock([TealOp(Op.err)])
errBlock = TealSimpleBlock([TealOp(self, Op.err)])

branchBlock = TealConditionalBlock([])
branchBlock.setTrueBlock(end)
Expand Down
3 changes: 2 additions & 1 deletion pyteal/ast/assert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def test_assert():

actual, _ = expr.__teal__()

assert actual == expected
with TealComponent.Context.ignoreExprEquality():
assert actual == expected

def test_assert_invalid():
with pytest.raises(TealTypeError):
Expand Down
2 changes: 1 addition & 1 deletion pyteal/ast/asset.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum

from ..types import TealType, require_type
from ..ir import TealOp, Op
from ..ir import Op
from .expr import Expr
from .leafexpr import LeafExpr
from .maybe import MaybeValue
Expand Down
Loading