You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: task_loop.go
    path of file: ./repos/erda/internal/tools/pipeline/providers/reconciler/taskrun
    
    the code of the file until where you have to start completion: // Copyright (c) 2021 Terminus, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package taskrun

import (
	"f
    
func (tr *TaskRun) handleTaskLoop() error {
	// if the task status is non-end or stopByUser, skip the loop
	if tr.Task.Status.IsShouldSkipLoop() {
		return nil
	}

	// No loop configuration skip
	if tr.Task.Extra.LoopOptions == nil || tr.Task.Extra.LoopOptions.CalculatedLoop == nil {
		return nil
	}
	loopOpt := tr.Task.Extra.LoopOptions.CalculatedLoop
	loopedTimes := tr.Task.Extra.LoopOptions.LoopedTimes
	expr := loopOpt.Break
	// no Strategy use Default strategy
	if loopOpt.Strategy == nil {
		loopOpt.Strategy = &apistructs.PipelineTaskDefaultLoopStrategy
	}
	// Determine whether the exit conditions are still not met
	params := pexpr_params.GenerateParamsFromTask(tr.P.ID, tr.Task.ID, tr.Task.Status)
	result, err := pexpr.Eval(expr, params)
	if err != nil {
		rlog.Errorf("loop break expr %s evaluate failed, err: %v", expr, err)
		result = false
	}
	// Meet the exit conditions, exit the loop
	if t, ok := result.(bool); ok && t {
		rlog.TWarnf(tr.P.ID, tr.Task.ID, "loop break expr %s evaluate result is true, break loop", expr)
		return nil
	}
	// The maximum number of cycles has been reached, exit the loop
	if loopOpt.Strategy.MaxTimes != -1 && int64(loopedTimes) >= loopOpt.Strategy.MaxTimes {
		rlog.TDebugf(tr.P.ID, tr.Task.ID, "loop reached max times %d, stop loop", loopedTimes)
		return nil
	}
	rlog.TDebugf(tr.P.ID, tr.Task.ID, "loop break expr %s evaluate result is false, continue loop", expr)

	// reportTaskForLoop report task before resetTaskForLoop to avoid missing task info
	if err := tr.reportTaskForLoop(); err != nil {
		rlog.Errorf("failed to report task-loop, pipelineID: %d, taskID: %d, err: %v", tr.P.ID, tr.Task.ID, err)
	}

	tr.resetTaskForLoop()
	return nil
}