From 1d7cd6ad0b5b01eec9a9e3fa428020eb42493b4b Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 09:56:48 -0400 Subject: [PATCH 1/9] add frame ops to avm8 branch --- pyteal/__init__.pyi | 6 ++ pyteal/ast/__init__.py | 7 ++ pyteal/ast/frame.py | 188 +++++++++++++++++++++++++++++++++++++++ pyteal/ast/frame_test.py | 159 +++++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 8 +- 5 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 pyteal/ast/frame.py create mode 100644 pyteal/ast/frame_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ce347b0eb..69e3c55eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -70,6 +70,7 @@ __all__ = [ "BoxReplace", "Break", "Btoi", + "Bury", "Bytes", "BytesAdd", "BytesAnd", @@ -98,6 +99,7 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", + "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -115,6 +117,8 @@ __all__ = [ "ExtractUint32", "ExtractUint64", "For", + "FrameBury", + "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -173,7 +177,9 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", + "PopN", "Pragma", + "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 9efe807c5..1ca49a2e5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,6 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury # misc from pyteal.ast.scratch import ( @@ -336,6 +337,12 @@ "For", "Break", "Continue", + "Proto", + "FrameDig", + "FrameBury", + "Bury", + "DupN", + "PopN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py new file mode 100644 index 000000000..8b1cb6080 --- /dev/null +++ b/pyteal/ast/frame.py @@ -0,0 +1,188 @@ +from typing import TYPE_CHECKING + +from pyteal.ast.expr import Expr +from pyteal.types import TealType, require_type +from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class Proto(Expr): + def __init__(self, arg_num: int, ret_num: int): + super().__init__() + if arg_num < 0: + raise TealInputError(f"subroutine arg number {arg_num} must be >= 0") + if ret_num < 0: + raise TealInputError(f"return value number {ret_num} must be >= 0") + self.arg_num = arg_num + self.ret_num = ret_num + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.proto.min_version, + options.version, + "Program version too low to use op proto", + ) + op = TealOp(self, Op.proto, self.arg_num, self.ret_num) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num})" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +Proto.__module__ = "pyteal" + + +class FrameDig(Expr): + def __init__(self, depth: int): + super().__init__() + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_dig.min_version, + options.version, + "Program version too low to use op frame_dig", + ) + op = TealOp(self, Op.frame_dig, self.depth) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(frame_dig: dig_depth = {self.depth})" + + def type_of(self) -> TealType: + return TealType.anytype + + def has_return(self) -> bool: + return False + + +FrameDig.__module__ = "pyteal" + + +class FrameBury(Expr): + def __init__(self, what: Expr, depth: int): + super().__init__() + require_type(what, TealType.anytype) + self.what = what + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_bury.min_version, + options.version, + "Program version too low to use op frame_bury", + ) + op = TealOp(self, Op.frame_bury, self.depth) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(frame_bury (bury_depth = {self.depth}) ({self.what}))" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +FrameBury.__module__ = "pyteal" + + +class Bury(Expr): + def __init__(self, what: Expr, depth: int): + super().__init__() + require_type(what, TealType.anytype) + if depth <= 0: + raise TealInputError("bury depth should be strictly positive") + self.what = what + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.bury.min_version, + options.version, + "Program version too low to use op bury", + ) + op = TealOp(self, Op.bury, self.depth) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(bury (depth = {self.depth}) ({self.what}))" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +Bury.__module__ = "pyteal" + + +class DupN(Expr): + def __init__(self, what: Expr, repetition: int): + super().__init__() + require_type(what, TealType.anytype) + if repetition < 0: + raise TealInputError("dupn repetition should be non negative") + self.what = what + self.repetition = repetition + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.dupn.min_version, + options.version, + "Program version too low to use op dupn", + ) + op = TealOp(self, Op.dupn, self.repetition) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(dupn (repetition = {self.repetition}) ({self.what}))" + + def type_of(self) -> TealType: + return self.what.type_of() + + def has_return(self) -> bool: + return False + + +DupN.__module__ = "pyteal" + + +class PopN(Expr): + def __init__(self, repetition: int): + super().__init__() + if repetition < 0: + raise TealInputError("popn repetition should be non negative") + self.repetition = repetition + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.popn.min_version, + options.version, + "Program version too low to use op popn", + ) + op = TealOp(self, Op.popn, self.repetition) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(popn {self.repetition})" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +PopN.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py new file mode 100644 index 000000000..b21b47d0e --- /dev/null +++ b/pyteal/ast/frame_test.py @@ -0,0 +1,159 @@ +import pytest +import pyteal as pt +from pyteal.types import TealType + +avm7Options = pt.CompileOptions(version=7) +avm8Options = pt.CompileOptions(version=8) + + +@pytest.mark.parametrize("input_num, output_num", [(1, 1), (1, 0), (5, 5)]) +def test_proto(input_num: int, output_num: int): + expr = pt.Proto(input_num, output_num) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.proto, input_num, output_num)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_proto_invalid(): + with pytest.raises(pt.TealInputError): + pt.Proto(-1, 1) + + with pytest.raises(pt.TealInputError): + pt.Proto(1, -1) + + with pytest.raises(pt.TealInputError): + pt.Proto(1, 1).__teal__(avm7Options) + + +@pytest.mark.parametrize("depth", [-1, 0, 1, 2]) +def test_frame_dig(depth: int): + expr = pt.FrameDig(depth) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.anytype + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.frame_dig, depth)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_dig_invalid(): + with pytest.raises(pt.TealInputError): + pt.FrameDig(1).__teal__(avm7Options) + + +def test_frame_bury(): + byte_expr = pt.Bytes("Astartes") + expr = pt.FrameBury(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.frame_bury, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_bury_invalid(): + with pytest.raises(pt.TealTypeError): + pt.FrameBury(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) + + +def test_bury(): + byte_expr = pt.Bytes("Astartes") + expr = pt.Bury(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.bury, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_bury_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Bury(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.Bury(pt.Int(1), 0) + + with pytest.raises(pt.TealInputError): + pt.Bury(pt.Int(1), 1).__teal__(avm7Options) + + +@pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) +def test_popn(repetition: int): + expr = pt.PopN(repetition) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.popn, repetition)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_popn_invalid(): + with pytest.raises(pt.TealInputError): + pt.PopN(-1) + + with pytest.raises(pt.TealInputError): + pt.PopN(5).__teal__(avm7Options) + + +def test_dupn(): + byte_expr = pt.Bytes("Astartes") + expr = pt.DupN(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == byte_expr.type_of() + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.dupn, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_dupn_invalid(): + with pytest.raises(pt.TealTypeError): + pt.DupN(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.DupN(pt.Int(1), -1) + + with pytest.raises(pt.TealInputError): + pt.DupN(pt.Int(1), 1).__teal__(avm7Options) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 43a62b5d4..9ec496288 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -33,7 +33,7 @@ def min_version(self) -> int: # fmt: off # meta comment = OpType("//", Mode.Signature | Mode.Application, 0) - # avm + # avm err = OpType("err", Mode.Signature | Mode.Application, 2) sha256 = OpType("sha256", Mode.Signature | Mode.Application, 2) keccak256 = OpType("keccak256", Mode.Signature | Mode.Application, 2) @@ -197,6 +197,12 @@ def min_version(self) -> int: box_len = OpType("box_len", Mode.Application, 8) box_get = OpType("box_get", Mode.Application, 8) box_put = OpType("box_put", Mode.Application, 8) + popn = OpType("popn", Mode.Signature | Mode.Application, 8) + dupn = OpType("dupn", Mode.Signature | Mode.Application, 8) + bury = OpType("bury", Mode.Signature | Mode.Application, 8) + frame_dig = OpType("frame_dig", Mode.Signature | Mode.Application, 8) + frame_bury = OpType("frame_bury", Mode.Signature | Mode.Application, 8) + proto = OpType("proto", Mode.Signature | Mode.Application, 8) # fmt: on From 49d169ed4e7dd4bbd7ea1cedcdc5a5d70718d33d Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 13:52:43 -0400 Subject: [PATCH 2/9] specify FRAME_POINTER_VERSION in frame-op branch --- pyteal/__init__.py | 2 ++ pyteal/__init__.pyi | 2 ++ pyteal/compiler/__init__.py | 2 ++ pyteal/compiler/compiler.py | 1 + 4 files changed, 7 insertions(+) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ac28dd641..ba6e8eead 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,6 +8,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -38,6 +39,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 69e3c55eb..40600d561 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,6 +11,7 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -116,6 +117,7 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", + "FRAME_POINTER_VERSION", "For", "FrameBury", "FrameDig", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index e0d29450d..9755ead4f 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,6 +3,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -16,6 +17,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 1955d0430..f2b25b489 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -26,6 +26,7 @@ from pyteal.compiler.constants import createConstantBlocks MAX_PROGRAM_VERSION = 8 +FRAME_POINTER_VERSION = 8 MIN_PROGRAM_VERSION = 2 DEFAULT_PROGRAM_VERSION = MIN_PROGRAM_VERSION From 5840a8bb772416254c3ab8cc5cc11c5278912e02 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 1 Nov 2022 14:19:15 -0400 Subject: [PATCH 3/9] per review comments --- pyteal/ast/frame.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 8b1cb6080..5799ef90b 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -10,14 +10,18 @@ class Proto(Expr): - def __init__(self, arg_num: int, ret_num: int): + def __init__(self, num_args: int, num_returns: int): super().__init__() - if arg_num < 0: - raise TealInputError(f"subroutine arg number {arg_num} must be >= 0") - if ret_num < 0: - raise TealInputError(f"return value number {ret_num} must be >= 0") - self.arg_num = arg_num - self.ret_num = ret_num + if num_args < 0: + raise TealInputError( + f"the number of arguments provided to Proto must be >= 0 but {num_args=}" + ) + if num_returns < 0: + raise TealInputError( + f"the number of return values provided to Proto must be >= 0 but {num_returns=}" + ) + self.num_args = num_args + self.num_returns = num_returns def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -25,11 +29,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op proto", ) - op = TealOp(self, Op.proto, self.arg_num, self.ret_num) + op = TealOp(self, Op.proto, self.num_args, self.num_returns) return TealBlock.FromOp(options, op) def __str__(self) -> str: - return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num})" + return f"(proto: num_args = {self.num_args}, num_returns = {self.num_returns})" def type_of(self) -> TealType: return TealType.none From a596fc15472029b2445f6e7351c4c18bdbb9a616 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 08:42:32 -0400 Subject: [PATCH 4/9] per review comments --- pyteal/ast/frame.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 5799ef90b..7334a39b6 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -73,10 +73,10 @@ def has_return(self) -> bool: class FrameBury(Expr): - def __init__(self, what: Expr, depth: int): + def __init__(self, value: Expr, depth: int): super().__init__() - require_type(what, TealType.anytype) - self.what = what + require_type(value, TealType.anytype) + self.value = value self.depth = depth def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -86,10 +86,10 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op frame_bury", ) op = TealOp(self, Op.frame_bury, self.depth) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(frame_bury (bury_depth = {self.depth}) ({self.what}))" + return f"(frame_bury (bury_depth = {self.depth}) ({self.value}))" def type_of(self) -> TealType: return TealType.none @@ -102,12 +102,12 @@ def has_return(self) -> bool: class Bury(Expr): - def __init__(self, what: Expr, depth: int): + def __init__(self, value: Expr, depth: int): super().__init__() - require_type(what, TealType.anytype) + require_type(value, TealType.anytype) if depth <= 0: raise TealInputError("bury depth should be strictly positive") - self.what = what + self.value = value self.depth = depth def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -117,10 +117,10 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op bury", ) op = TealOp(self, Op.bury, self.depth) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(bury (depth = {self.depth}) ({self.what}))" + return f"(bury (depth = {self.depth}) ({self.value}))" def type_of(self) -> TealType: return TealType.none @@ -133,12 +133,12 @@ def has_return(self) -> bool: class DupN(Expr): - def __init__(self, what: Expr, repetition: int): + def __init__(self, value: Expr, repetition: int): super().__init__() - require_type(what, TealType.anytype) + require_type(value, TealType.anytype) if repetition < 0: raise TealInputError("dupn repetition should be non negative") - self.what = what + self.value = value self.repetition = repetition def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -148,13 +148,13 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op dupn", ) op = TealOp(self, Op.dupn, self.repetition) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(dupn (repetition = {self.repetition}) ({self.what}))" + return f"(dupn (repetition = {self.repetition}) ({self.value}))" def type_of(self) -> TealType: - return self.what.type_of() + return self.value.type_of() def has_return(self) -> bool: return False From 519c7528b6f301d077bf3133ba41f6dab1d06e74 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 08:46:45 -0400 Subject: [PATCH 5/9] per review comments, depth -> frame_depth --- pyteal/ast/frame.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 7334a39b6..68ce3a2f2 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -46,9 +46,9 @@ def has_return(self) -> bool: class FrameDig(Expr): - def __init__(self, depth: int): + def __init__(self, frame_index: int): super().__init__() - self.depth = depth + self.frame_index = frame_index def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -56,11 +56,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op frame_dig", ) - op = TealOp(self, Op.frame_dig, self.depth) + op = TealOp(self, Op.frame_dig, self.frame_index) return TealBlock.FromOp(options, op) def __str__(self) -> str: - return f"(frame_dig: dig_depth = {self.depth})" + return f"(frame_dig: dig_from = {self.frame_index})" def type_of(self) -> TealType: return TealType.anytype @@ -73,11 +73,11 @@ def has_return(self) -> bool: class FrameBury(Expr): - def __init__(self, value: Expr, depth: int): + def __init__(self, value: Expr, frame_index: int): super().__init__() require_type(value, TealType.anytype) self.value = value - self.depth = depth + self.frame_index = frame_index def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -85,11 +85,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op frame_bury", ) - op = TealOp(self, Op.frame_bury, self.depth) + op = TealOp(self, Op.frame_bury, self.frame_index) return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(frame_bury (bury_depth = {self.depth}) ({self.value}))" + return f"(frame_bury (bury_to = {self.frame_index}) ({self.value}))" def type_of(self) -> TealType: return TealType.none From 0924d94de17751eed420349717341d6064913f75 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:11:45 -0400 Subject: [PATCH 6/9] take bury out --- pyteal/__init__.pyi | 1 - pyteal/ast/__init__.py | 3 +-- pyteal/ast/frame.py | 31 ------------------------------- pyteal/ast/frame_test.py | 30 ------------------------------ 4 files changed, 1 insertion(+), 64 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 40600d561..7682ab0b7 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -71,7 +71,6 @@ __all__ = [ "BoxReplace", "Break", "Btoi", - "Bury", "Bytes", "BytesAdd", "BytesAnd", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1ca49a2e5..a1b21e071 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN # misc from pyteal.ast.scratch import ( @@ -340,7 +340,6 @@ "Proto", "FrameDig", "FrameBury", - "Bury", "DupN", "PopN", "Router", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 68ce3a2f2..9260d3064 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -101,37 +101,6 @@ def has_return(self) -> bool: FrameBury.__module__ = "pyteal" -class Bury(Expr): - def __init__(self, value: Expr, depth: int): - super().__init__() - require_type(value, TealType.anytype) - if depth <= 0: - raise TealInputError("bury depth should be strictly positive") - self.value = value - self.depth = depth - - def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: - verifyProgramVersion( - Op.bury.min_version, - options.version, - "Program version too low to use op bury", - ) - op = TealOp(self, Op.bury, self.depth) - return TealBlock.FromOp(options, op, self.value) - - def __str__(self) -> str: - return f"(bury (depth = {self.depth}) ({self.value}))" - - def type_of(self) -> TealType: - return TealType.none - - def has_return(self) -> bool: - return False - - -Bury.__module__ = "pyteal" - - class DupN(Expr): def __init__(self, value: Expr, repetition: int): super().__init__() diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index b21b47d0e..8bbbf26c1 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -77,36 +77,6 @@ def test_frame_bury_invalid(): pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) -def test_bury(): - byte_expr = pt.Bytes("Astartes") - expr = pt.Bury(byte_expr, 4) - assert not expr.has_return() - assert expr.type_of() == TealType.none - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), - pt.TealOp(expr, pt.Op.bury, 4), - ] - ) - actual, _ = expr.__teal__(avm8Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - assert actual == expected - - -def test_bury_invalid(): - with pytest.raises(pt.TealTypeError): - pt.Bury(pt.Seq(), 1) - - with pytest.raises(pt.TealInputError): - pt.Bury(pt.Int(1), 0) - - with pytest.raises(pt.TealInputError): - pt.Bury(pt.Int(1), 1).__teal__(avm7Options) - - @pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) def test_popn(repetition: int): expr = pt.PopN(repetition) From d1c52a2504d2190064533cdaf410bc613449fd3c Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:29:53 -0400 Subject: [PATCH 7/9] pop popn --- pyteal/__init__.pyi | 1 - pyteal/ast/__init__.py | 3 +-- pyteal/ast/frame.py | 29 ----------------------------- pyteal/ast/frame_test.py | 22 ---------------------- 4 files changed, 1 insertion(+), 54 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 7682ab0b7..19dcc01fb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -178,7 +178,6 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", - "PopN", "Pragma", "Proto", "RETURN_HASH_PREFIX", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index a1b21e071..4a0b4e181 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN +from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -341,7 +341,6 @@ "FrameDig", "FrameBury", "DupN", - "PopN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 9260d3064..8f5e24891 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -130,32 +130,3 @@ def has_return(self) -> bool: DupN.__module__ = "pyteal" - - -class PopN(Expr): - def __init__(self, repetition: int): - super().__init__() - if repetition < 0: - raise TealInputError("popn repetition should be non negative") - self.repetition = repetition - - def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: - verifyProgramVersion( - Op.popn.min_version, - options.version, - "Program version too low to use op popn", - ) - op = TealOp(self, Op.popn, self.repetition) - return TealBlock.FromOp(options, op) - - def __str__(self) -> str: - return f"(popn {self.repetition})" - - def type_of(self) -> TealType: - return TealType.none - - def has_return(self) -> bool: - return False - - -PopN.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index 8bbbf26c1..d02f526ba 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -77,28 +77,6 @@ def test_frame_bury_invalid(): pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) -@pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) -def test_popn(repetition: int): - expr = pt.PopN(repetition) - assert not expr.has_return() - assert expr.type_of() == pt.TealType.none - - expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.popn, repetition)]) - actual, _ = expr.__teal__(avm8Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - assert actual == expected - - -def test_popn_invalid(): - with pytest.raises(pt.TealInputError): - pt.PopN(-1) - - with pytest.raises(pt.TealInputError): - pt.PopN(5).__teal__(avm7Options) - - def test_dupn(): byte_expr = pt.Bytes("Astartes") expr = pt.DupN(byte_expr, 4) From 8c41726c6d663ee5aff5241062e91a42ce336f4c Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:04:58 -0400 Subject: [PATCH 8/9] unexport use of frame ops --- pyteal/__init__.pyi | 4 ---- pyteal/ast/__init__.py | 5 ----- pyteal/ast/frame_test.py | 30 +++++++++++++++--------------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 19dcc01fb..3f69e10bd 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -99,7 +99,6 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", - "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -118,8 +117,6 @@ __all__ = [ "ExtractUint64", "FRAME_POINTER_VERSION", "For", - "FrameBury", - "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -179,7 +176,6 @@ __all__ = [ "Or", "Pop", "Pragma", - "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 4a0b4e181..9efe807c5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,6 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -337,10 +336,6 @@ "For", "Break", "Continue", - "Proto", - "FrameDig", - "FrameBury", - "DupN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index d02f526ba..e4cde2aa4 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -1,6 +1,6 @@ import pytest import pyteal as pt -from pyteal.types import TealType +from pyteal.ast.frame import FrameBury, FrameDig, Proto, DupN avm7Options = pt.CompileOptions(version=7) avm8Options = pt.CompileOptions(version=8) @@ -8,7 +8,7 @@ @pytest.mark.parametrize("input_num, output_num", [(1, 1), (1, 0), (5, 5)]) def test_proto(input_num: int, output_num: int): - expr = pt.Proto(input_num, output_num) + expr = Proto(input_num, output_num) assert not expr.has_return() assert expr.type_of() == pt.TealType.none @@ -22,18 +22,18 @@ def test_proto(input_num: int, output_num: int): def test_proto_invalid(): with pytest.raises(pt.TealInputError): - pt.Proto(-1, 1) + Proto(-1, 1) with pytest.raises(pt.TealInputError): - pt.Proto(1, -1) + Proto(1, -1) with pytest.raises(pt.TealInputError): - pt.Proto(1, 1).__teal__(avm7Options) + Proto(1, 1).__teal__(avm7Options) @pytest.mark.parametrize("depth", [-1, 0, 1, 2]) def test_frame_dig(depth: int): - expr = pt.FrameDig(depth) + expr = FrameDig(depth) assert not expr.has_return() assert expr.type_of() == pt.TealType.anytype @@ -47,14 +47,14 @@ def test_frame_dig(depth: int): def test_frame_dig_invalid(): with pytest.raises(pt.TealInputError): - pt.FrameDig(1).__teal__(avm7Options) + FrameDig(1).__teal__(avm7Options) def test_frame_bury(): byte_expr = pt.Bytes("Astartes") - expr = pt.FrameBury(byte_expr, 4) + expr = FrameBury(byte_expr, 4) assert not expr.has_return() - assert expr.type_of() == TealType.none + assert expr.type_of() == pt.TealType.none expected = pt.TealSimpleBlock( [ @@ -71,15 +71,15 @@ def test_frame_bury(): def test_frame_bury_invalid(): with pytest.raises(pt.TealTypeError): - pt.FrameBury(pt.Seq(), 1) + FrameBury(pt.Seq(), 1) with pytest.raises(pt.TealInputError): - pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) + FrameBury(pt.Int(1), 1).__teal__(avm7Options) def test_dupn(): byte_expr = pt.Bytes("Astartes") - expr = pt.DupN(byte_expr, 4) + expr = DupN(byte_expr, 4) assert not expr.has_return() assert expr.type_of() == byte_expr.type_of() @@ -98,10 +98,10 @@ def test_dupn(): def test_dupn_invalid(): with pytest.raises(pt.TealTypeError): - pt.DupN(pt.Seq(), 1) + DupN(pt.Seq(), 1) with pytest.raises(pt.TealInputError): - pt.DupN(pt.Int(1), -1) + DupN(pt.Int(1), -1) with pytest.raises(pt.TealInputError): - pt.DupN(pt.Int(1), 1).__teal__(avm7Options) + DupN(pt.Int(1), 1).__teal__(avm7Options) From dd3c54c3aa81ba91b71cf2c192eb901ada8870b3 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 16:33:01 -0400 Subject: [PATCH 9/9] hide FRAME_POINTER_VERISON --- pyteal/__init__.py | 2 -- pyteal/__init__.pyi | 2 -- pyteal/compiler/__init__.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ba6e8eead..ac28dd641 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,7 +8,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -39,7 +38,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 3f69e10bd..ce347b0eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,7 +11,6 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -115,7 +114,6 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", - "FRAME_POINTER_VERSION", "For", "Ge", "GeneratedID", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index 9755ead4f..e0d29450d 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,7 +3,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -17,7 +16,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions",