code: func loadLLB(def *pb.Definition, fn func(digest.Digest, *pb.Op, func(digest.Digest) (solver.Vertex, error)) (solver.Vertex, error)) (solver.Edge, error) {
  	if len(def.Def) == 0 {
  		return solver.Edge{}, errors.New("invalid empty definition")
  	}
  
  	allOps := make(map[digest.Digest]*pb.Op)
  
  	var dgst digest.Digest
  
  	for _, dt := range def.Def {
  		var op pb.Op
  		if err := (&op).Unmarshal(dt); err != nil {
  			return solver.Edge{}, errors.Wrap(err, "failed to parse llb proto op")
  		}
  		dgst = digest.FromBytes(dt)
  		allOps[dgst] = &op
  	}
  
  	lastOp := allOps[dgst]
  	delete(allOps, dgst)
  	dgst = lastOp.Inputs[0].Digest
  
  	cache := make(map[digest.Digest]solver.Vertex)
  
  	var rec func(dgst digest.Digest) (solver.Vertex, error)
  	rec = func(dgst digest.Digest) (solver.Vertex, error) {
  		if v, ok := cache[dgst]; ok {
  			return v, nil
  		}
  		op, ok := allOps[dgst]
  		if !ok {
  			return nil, errors.Errorf("invalid missing input digest %s", dgst)
  		}
  		v, err := fn(dgst, op, rec)
  		if err != nil {
  			return nil, err
  		}
  		cache[dgst] = v
  		return v, nil
  	}
  
  	v, err := rec(dgst)
  	if err != nil {
  		return solver.Edge{}, err
  	}
  	return solver.Edge{Vertex: v, Index: solver.Index(lastOp.Inputs[0].Index)}, nil
  }
docs: // loadLLB loads LLB.
  // fn is executed sequentially.