def __teal__(self, options: "CompileOptions"): if len(self.cond) > 1: asserts: list[Expr] = [] for cond in self.cond: asrt = Assert(cond, comment=self.comment) asrt.trace = cond.trace asserts.append(asrt) return Seq(*asserts).__teal__(options) if options.version >= Op.assert_.min_version: # use assert op if available conds: list[Expr] = [self.cond[0]] if self.comment is not None: conds.append(Comment(self.comment)) return TealBlock.FromOp(options, TealOp(self, Op.assert_), *conds) # if assert op is not available, use branches and err condStart, condEnd = self.cond[0].__teal__(options) end = TealSimpleBlock([]) errBlock = TealSimpleBlock([TealOp(self, Op.err)]) branchBlock = TealConditionalBlock([]) branchBlock.setTrueBlock(end) branchBlock.setFalseBlock(errBlock) condEnd.setNextBlock(branchBlock) return condStart, end
def __teal__(self, options: "CompileOptions"): if self.doBlock is None: raise TealCompileError("While expression must have a doBlock", self) options.enterLoop() condStart, condEnd = self.cond.__teal__(options) doStart, doEnd = self.doBlock.__teal__(options) end = TealSimpleBlock([]) doEnd.setNextBlock(condStart) branchBlock = TealConditionalBlock([]) branchBlock.setTrueBlock(doStart) branchBlock.setFalseBlock(end) condEnd.setNextBlock(branchBlock) breakBlocks, continueBlocks = options.exitLoop() for block in breakBlocks: block.setNextBlock(end) for block in continueBlocks: block.setNextBlock(condStart) return condStart, end
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
def __teal__(self, options: "CompileOptions"): if options.version < Op.cover.min_version: raise TealCompileError( "WideRatio requires program version {} or higher".format( Op.cover.min_version ), self, ) numStart, numEnd = multiplyFactors(self, self.numeratorFactors, options) denomStart, denomEnd = multiplyFactors(self, self.denominatorFactors, options) numEnd.setNextBlock(denomStart) combine = TealSimpleBlock( [ TealOp(self, Op.divmodw), TealOp(self, Op.pop), # pop remainder low word TealOp(self, Op.pop), # pop remainder high word TealOp(self, Op.swap), # swap quotient high and low words TealOp(self, Op.logic_not), TealOp(self, Op.assert_), # assert quotient high word is 0 # end with quotient low word remaining on the stack ] ) denomEnd.setNextBlock(combine) return numStart, combine
def __teal__(self, options: "CompileOptions"): if not options.isInLoop(): raise TealCompileError("continue is only allowed in a loop", self) start = TealSimpleBlock([]) options.addLoopContinueBlock(start) return start, start
def __teal__(self, options: "CompileOptions"): start = None end = None for i, arg in enumerate(self.args): argStart, argEnd = arg.__teal__(options) if i == 0: start = argStart end = argEnd else: cast(TealSimpleBlock, end).setNextBlock(argStart) opBlock = TealSimpleBlock([TealOp(self, self.op)]) argEnd.setNextBlock(opBlock) end = opBlock return start, end
def __teal__(self, options: "CompileOptions"): if self.thenBranch is None: raise TealCompileError("If expression must have a thenBranch", self) condStart, condEnd = self.cond.__teal__(options) thenStart, thenEnd = self.thenBranch.__teal__(options) end = TealSimpleBlock([]) branchBlock = TealConditionalBlock([]) branchBlock.setTrueBlock(thenStart) condEnd.setNextBlock(branchBlock) thenEnd.setNextBlock(end) if self.elseBranch is None: branchBlock.setFalseBlock(end) else: elseStart, elseEnd = self.elseBranch.__teal__(options) branchBlock.setFalseBlock(elseStart) elseEnd.setNextBlock(end) return condStart, end
def multiplyFactors( expr: Expr, factors: List[Expr], options: "CompileOptions" ) -> Tuple[TealSimpleBlock, TealSimpleBlock]: if len(factors) == 0: raise TealInternalError("Received 0 factors") start = TealSimpleBlock([]) fac0Start, fac0End = factors[0].__teal__(options) if len(factors) == 1: # need to use 0 as high word highword = TealSimpleBlock([TealOp(expr, Op.int, 0)]) start.setNextBlock(highword) highword.setNextBlock(fac0Start) end = fac0End else: start.setNextBlock(fac0Start) fac1Start, fac1End = factors[1].__teal__(options) fac0End.setNextBlock(fac1Start) multiplyFirst2 = TealSimpleBlock([TealOp(expr, Op.mulw)]) fac1End.setNextBlock(multiplyFirst2) end = multiplyFirst2 for factor in factors[2:]: facXStart, facXEnd = factor.__teal__(options) end.setNextBlock(facXStart) # stack is [..., A, B, C], where C is current factor # need to pop all A,B,C from stack and push X,Y, where X and Y are: # X * 2**64 + Y = (A * 2**64 + B) * C # <=> X * 2**64 + Y = A * C * 2**64 + B * C # <=> X = A * C + highword(B * C) # Y = lowword(B * C) multiply = TealSimpleBlock( [ TealOp(expr, Op.uncover, 2), # stack: [..., B, C, A] TealOp(expr, Op.dig, 1), # stack: [..., B, C, A, C] TealOp(expr, Op.mul), # stack: [..., B, C, A*C] TealOp(expr, Op.cover, 2), # stack: [..., A*C, B, C] TealOp( expr, Op.mulw ), # stack: [..., A*C, highword(B*C), lowword(B*C)] TealOp( expr, Op.cover, 2 ), # stack: [..., lowword(B*C), A*C, highword(B*C)] TealOp( expr, Op.add ), # stack: [..., lowword(B*C), A*C+highword(B*C)] TealOp( expr, Op.swap ), # stack: [..., A*C+highword(B*C), lowword(B*C)] ] ) facXEnd.setNextBlock(multiply) end = multiply return start, end