Skip to content

Commit

Permalink
Frame pointer usage in subroutine (#562)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahangsu committed Dec 3, 2022
1 parent 2d65bb6 commit de90e93
Show file tree
Hide file tree
Showing 103 changed files with 13,255 additions and 433 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Unreleased

# Added
* Added frame pointer support for subroutine arguments, replacing the previous usage of scratch. ([#562](https://github.com/algorand/pyteal/pull/562))

# Fixed
* Allowing the `MethodCall` and `ExecuteMethodCall` to be passed `None` as app_id argument in the case of an app create transaction ([#592](https://github.com/algorand/pyteal/pull/592))

# Changed
* Introducing `AbstractVar` to abstract value access: store, load, and stack type. ([#584](https://github.com/algorand/pyteal/pull/584))
* NOTE: a backwards incompatable change was imposed in this PR: previous ABI value's public member `stored_value` with type `ScratchVar`, is now changed to protected member `_stored_value` with type `AbstractVar`.

# 0.20.1

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ services:
- "4160:4160" # gossip
- "9100:9100" # prometheus
environment:
- DEV_MODE
- DEV_MODE=true
- TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
healthcheck:
test: goal node status || exit 1
test: goal node status
interval: 2s
retries: 10
7 changes: 7 additions & 0 deletions pyteal/ast/abi/tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,13 @@ def __setattr__(self, name: str, field: Any) -> None:
if name == "_NamedTuple__ready" or not self.__ready:
super().__setattr__(name, field)
return
# NOTE this pass condition is for following scenario:
# NamedTuple is an argument, and inside subroutine, subroutine set internal ABI value with FrameStorage
# This used to violate `__setattr__` for not allowing any assignment to attributes
# Now this case is lifted such that we can shift the storage scheme.
if name == "_stored_value" and self.__ready:
super().__setattr__(name, field)
return
raise TealInputError("cannot assign to NamedTuple attributes.")


Expand Down
23 changes: 13 additions & 10 deletions pyteal/ast/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,13 @@ def __init__(
f"be greater than local allocations {len(local_stack_types)}."
)

if not all(map(lambda t: t != TealType.none, arg_stack_types)):
if any(t == TealType.none for t in arg_stack_types + local_stack_types):
raise TealInternalError("Variables in frame memory layout must be typed.")

self.num_return_allocs: int = num_return_allocs
self.arg_stack_types: list[TealType] = arg_stack_types
self.local_stack_types: list[TealType] = local_stack_types

# Type check of local variables are performed over LocalTypeSegments
self.succinct_repr: list[LocalTypeSegment] = [
LocalTypeSegment(t_type, len(list(dup_seg)))
for t_type, dup_seg in groupby(self.local_stack_types)
]

def __getitem__(self, index: int) -> TealType:
if index < 0:
return self.arg_stack_types[len(self.arg_stack_types) + index]
Expand All @@ -116,10 +110,19 @@ def has_return(self) -> bool:
def type_of(self) -> TealType:
return TealType.none

def _succinct_repr(self) -> list[LocalTypeSegment]:
return [
LocalTypeSegment(t_type, len(list(dup_seg)))
for t_type, dup_seg in groupby(self.local_stack_types)
]

def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]:
srt = TealSimpleBlock([])
end = srt
for iter_seg in self.succinct_repr:

# Type check of local variables are performed over LocalTypeSegments
succinct_repr: list[LocalTypeSegment] = self._succinct_repr()
for iter_seg in succinct_repr:
seg_srt, seg_end = iter_seg.__teal__(options)
end.setNextBlock(seg_srt)
end = seg_end
Expand Down Expand Up @@ -201,7 +204,7 @@ class FrameDig(Expr):
"""An expression that digs a value from a position around frame pointer.
This class is intentionally hidden because it's too basic to directly expose.
his is used only internally by FrameVar.
This is used only internally by FrameVar.
"""

def __init__(self, frame_index: int, *, inferred_type: Optional[TealType] = None):
Expand Down Expand Up @@ -235,7 +238,7 @@ class FrameBury(Expr):
"""An expression that buries a value to a position around frame pointer.
This class is intentionally hidden because it's too basic to directly expose.
his is used only internally by FrameVar.
This is used only internally by FrameVar.
"""

def __init__(
Expand Down
2 changes: 1 addition & 1 deletion pyteal/ast/frame_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,5 +305,5 @@ class SuccinctReprTestCase:
],
)
def test_proto_stack_layout_succinct_repr(testcase: SuccinctReprTestCase):
actual = ProtoStackLayout([], testcase.local_types, False).succinct_repr
actual = ProtoStackLayout([], testcase.local_types, False)._succinct_repr()
assert actual == testcase.expected
3 changes: 3 additions & 0 deletions pyteal/ast/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ def compile_program(
version: int = DEFAULT_TEAL_VERSION,
assemble_constants: bool = False,
optimize: OptimizeOptions = None,
frame_pointers: Optional[bool] = None,
) -> tuple[str, str, sdk_abi.Contract]:
"""
Constructs and compiles approval and clear-state programs from the registered methods and
Expand All @@ -749,13 +750,15 @@ def compile_program(
version=version,
assembleConstants=assemble_constants,
optimize=optimize,
frame_pointers=frame_pointers,
)
csp_compiled = compileTeal(
csp,
Mode.Application,
version=version,
assembleConstants=assemble_constants,
optimize=optimize,
frame_pointers=frame_pointers,
)
return ap_compiled, csp_compiled, contract

Expand Down

0 comments on commit de90e93

Please sign in to comment.