Esempio n. 1
0
    def __teal__(self, options: "CompileOptions"):
        if not isinstance(self.start, Int):
            return TernaryExpr(
                Op.replace3,
                (TealType.bytes, TealType.uint64, TealType.bytes),
                TealType.bytes,
                self.original,
                self.start,
                self.replacement,
            ).__teal__(options)

        op = self.__get_op(options)

        verifyProgramVersion(
            op.min_version,
            options.version,
            "Program version too low to use op {}".format(op),
        )

        s = cast(Int, self.start).value
        if op == Op.replace2:
            return TealBlock.FromOp(options, TealOp(self, op, s),
                                    self.original, self.replacement)
        elif op == Op.replace3:
            return TealBlock.FromOp(options, TealOp(self, op), self.original,
                                    self.start, self.replacement)
Esempio n. 2
0
    def __teal__(self, options: "CompileOptions"):
        op = self.__get_op(options)

        verifyProgramVersion(
            op.min_version,
            options.version,
            "Program version too low to use op {}".format(op),
        )

        if op == Op.extract:
            # if possible, exploit optimization in the extract opcode that takes the suffix
            # when the length argument is 0
            return TealBlock.FromOp(
                options,
                TealOp(self, op,
                       cast(Int, self.startArg).value, 0),
                self.stringArg,
            )
        elif op == Op.substring3:
            strBlockStart, strBlockEnd = self.stringArg.__teal__(options)
            nextBlockStart, nextBlockEnd = self.startArg.__teal__(options)
            strBlockEnd.setNextBlock(nextBlockStart)

            finalBlock = TealSimpleBlock([
                TealOp(self, Op.dig, 1),
                TealOp(self, Op.len),
                TealOp(self, Op.substring3),
            ])

            nextBlockEnd.setNextBlock(finalBlock)
            return strBlockStart, finalBlock
Esempio n. 3
0
    def __teal__(self, options: "CompileOptions"):
        if not isinstance(self.startArg, Int) or not isinstance(
                self.lenArg, Int):
            return TernaryExpr(
                Op.extract3,
                (TealType.bytes, TealType.uint64, TealType.uint64),
                TealType.bytes,
                self.stringArg,
                self.startArg,
                self.lenArg,
            ).__teal__(options)

        op = self.__get_op(options)

        verifyProgramVersion(
            op.min_version,
            options.version,
            "Program version too low to use op {}".format(op),
        )

        s, l = cast(Int, self.startArg).value, cast(Int, self.lenArg).value
        if op == Op.extract:
            return TealBlock.FromOp(options, TealOp(self, op, s, l),
                                    self.stringArg)
        elif op == Op.extract3:
            return TealBlock.FromOp(
                options,
                TealOp(self, op),
                self.stringArg,
                self.startArg,
                self.lenArg,
            )
Esempio n. 4
0
    def __teal__(self, options: "CompileOptions"):
        verifyProgramVersion(
            self.op.min_version,
            options.version,
            "Program version too low to use op {}".format(self.op),
        )

        return TealBlock.FromOp(options, TealOp(self, self.op), self.arg)
Esempio n. 5
0
    def __teal__(self, options: "CompileOptions"):
        verifyProgramVersion(
            Op.itxn_field.min_version,
            options.version,
            "Program version too low to create inner transactions",
        )

        return TealBlock.FromOp(
            options, TealOp(self, Op.itxn_field, self.field.arg_name), self.value
        )
Esempio n. 6
0
    def __teal__(self, options: "CompileOptions"):
        op = self.action.value

        verifyProgramVersion(
            op.min_version,
            options.version,
            "Program version too low to create inner transactions",
        )

        return TealBlock.FromOp(options, TealOp(self, op))
Esempio n. 7
0
    def __teal__(self, options: "CompileOptions"):
        verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version)
        verifyProgramVersion(
            self.op.min_version,
            options.version,
            "Program version too low to use op {}".format(self.op),
        )

        op = TealOp(self, self.op, self.field.arg_name)
        return TealBlock.FromOp(options, op)
Esempio n. 8
0
    def __teal__(self, options: "CompileOptions"):
        verifyFieldVersion(self.field.arg_name, self.field.min_version,
                           options.version)

        verifyProgramVersion(
            Op.gitxn.min_version,
            options.version,
            "Program version too low to use gitxn",
        )
        op = TealOp(self, Op.gitxn, self.txnIndex, self.field.arg_name)
        return TealBlock.FromOp(options, op)
Esempio n. 9
0
    def __teal__(self, options: "CompileOptions"):
        verifyProgramVersion(
            Op.json_ref.min_version,
            options.version,
            "Program version too low to use op json_ref",
        )

        verifyFieldVersion(self.type.arg_name, self.type.min_version,
                           options.version)

        op = TealOp(self, Op.json_ref, self.type.arg_name)
        return TealBlock.FromOp(options, op, self.json_obj, self.key)
Esempio n. 10
0
    def __teal__(self, options: "CompileOptions"):
        if type(self.index) is int:
            op = TealOp(self, Op.arg, self.index)
            return TealBlock.FromOp(options, op)

        verifyProgramVersion(
            Op.args.min_version,
            options.version,
            "Program version too low to use dynamic indexes with Arg",
        )

        op = TealOp(self, Op.args)
        return TealBlock.FromOp(options, op, cast(Expr, self.index))
Esempio n. 11
0
    def __teal__(self, options: "CompileOptions"):
        verifyProgramVersion(
            Op.gaid.min_version,
            options.version,
            "Program version too low to use Gaid expression",
        )

        if type(self.txnIndex) is int:
            op = TealOp(self, Op.gaid, self.txnIndex)
            return TealBlock.FromOp(options, op)

        op = TealOp(self, Op.gaids)
        return TealBlock.FromOp(options, op, cast(Expr, self.txnIndex))
Esempio n. 12
0
    def __teal__(self, options: "CompileOptions"):
        if options.currentSubroutine is not None:
            verifyProgramVersion(
                Op.retsub.min_version,
                options.version,
                "Program version too low to use subroutines",
            )
            returnType = options.currentSubroutine.return_type
            if returnType == TealType.none:
                if self.value is not None:
                    raise TealCompileError(
                        "Cannot return a value from a subroutine with return type TealType.none",
                        self,
                    )
            else:
                if self.value is None:
                    raise TealCompileError(
                        "A subroutine declares it returns a value, but no value is being returned",
                        self,
                    )
                actualType = self.value.type_of()
                if not types_match(actualType, returnType):
                    raise TealCompileError(
                        "Incompatible return type from subroutine, expected {} but got {}"
                        .format(returnType, actualType),
                        self,
                    )
            op = Op.retsub
        else:
            if self.value is None:
                raise TealCompileError(
                    "Return from main program must have an argument", self)
            actualType = self.value.type_of()
            if not types_match(actualType, TealType.uint64):
                raise TealCompileError(
                    "Incompatible return type from main program, expected {} but got {}"
                    .format(TealType.uint64, actualType),
                    self,
                )
            op = Op.return_

        args = [] if self.value is None else [self.value]
        return TealBlock.FromOp(options, TealOp(self, op), *args)
Esempio n. 13
0
    def __teal__(self, options: "CompileOptions"):
        verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version)

        opToUse = self.staticOp if type(self.index) is int else self.dynamicOp
        if opToUse is None:
            raise TealCompileError("Dynamic array indexing not supported", self)

        verifyProgramVersion(
            opToUse.min_version,
            options.version,
            "Program version too low to use op {}".format(opToUse),
        )

        if type(self.index) is int:
            op = TealOp(self, opToUse, self.field.arg_name, self.index)
            return TealBlock.FromOp(options, op)

        op = TealOp(self, opToUse, self.field.arg_name)
        return TealBlock.FromOp(options, op, cast(Expr, self.index))
Esempio n. 14
0
    def __teal__(self, options: "CompileOptions"):
        verifyFieldVersion(self.field.arg_name, self.field.min_version,
                           options.version)

        if type(self.index) is int:
            opToUse = Op.gitxna
        else:
            opToUse = Op.gitxnas

        verifyProgramVersion(
            opToUse.min_version,
            options.version,
            "Program version too low to use op {}".format(opToUse),
        )

        if type(self.index) is int:
            op = TealOp(self, opToUse, self.txnIndex, self.field.arg_name,
                        self.index)
            return TealBlock.FromOp(options, op)
        op = TealOp(self, opToUse, self.txnIndex, self.field.arg_name)
        return TealBlock.FromOp(options, op, cast(Expr, self.index))
Esempio n. 15
0
    def __teal__(self, options: "CompileOptions"):
        verifyFieldVersion(self.field.arg_name, self.field.min_version,
                           options.version)

        if type(self.txnIndex) is int:
            verifyProgramVersion(
                Op.gtxn.min_version,
                options.version,
                "Program version too low to use gtxn",
            )
            op = TealOp(self, Op.gtxn, self.txnIndex, self.field.arg_name)
            return TealBlock.FromOp(options, op)

        verifyProgramVersion(
            Op.gtxns.min_version,
            options.version,
            "Program version too low to index Gtxn with dynamic values",
        )

        op = TealOp(self, Op.gtxns, self.field.arg_name)
        return TealBlock.FromOp(options, op, cast(Expr, self.txnIndex))
Esempio n. 16
0
    def __teal__(self, options: "CompileOptions"):
        """
        Generate the subroutine's start and end teal blocks.
        The subroutine's arguments are pushed on the stack to be picked up into local scratch variables.
        There are 4 cases to consider for the pushed arg expression:

        1. (by-value) In the case of typical arguments of type Expr, the expression ITSELF is evaluated for the stack
            and will be stored in a local ScratchVar for subroutine evaluation

        2. (by-reference) In the case of a by-reference argument of type ScratchVar, its SLOT INDEX is put on the stack
            and will be stored in a local DynamicScratchVar for subroutine evaluation

        3. (ABI, or a special case in by-value) In this case, the storage of an ABI value are loaded
            to the stack and will be stored in a local ABI value for subroutine evaluation

        4. (ABI output keyword argument) In this case, we do not place ABI values (encoding) on the stack.
            This is an *output-only* argument: in `evaluate_subroutine` an ABI typed instance for subroutine evaluation
            will be generated, and gets in to construct the subroutine implementation.
        """
        verifyProgramVersion(
            Op.callsub.min_version,
            options.version,
            "Program version too low to use SubroutineCall expression",
        )

        def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr:
            if isinstance(arg, ScratchVar):
                return arg.index()
            elif isinstance(arg, Expr):
                return arg
            elif isinstance(arg, abi.BaseType):
                return arg.stored_value.load()
            else:
                raise TealInputError(
                    f"cannot handle current arg: {arg} to put it on stack"
                )

        op = TealOp(self, Op.callsub, self.subroutine)
        return TealBlock.FromOp(options, op, *[handle_arg(x) for x in self.args])