#include <bits/stdc++.h>
using namespace std;
template <typename T>
using V = vector<T>;
int gcdex(int a, int b, int &x, int &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  int x1, y1;
  int g = gcdex(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return g;
}
inline int ADD_MOD(int a, int b) { return (a + b) % 1000000007; }
inline int MUL_MOD(int a, int b) { return (int64_t(a) * b) % 1000000007; }
inline int SUB_MOD(int a, int b) { return a >= b ? a - b : a + 1000000007 - b; }
int DIV_MOD(int a, int b) {
  int x, y;
  gcdex(b, 1000000007, x, y);
  int b1 = (x % 1000000007 + 1000000007) % 1000000007;
  return MUL_MOD(a, b1);
}
const long double EPS = 1. / 1e9;
inline bool EPS_EQUAL(long double a, long double b) {
  return abs(a - b) <= EPS;
}
inline bool EPS_LESS(long double a, long double b) { return b - a > EPS; }
inline bool EPS_GREATER(long double a, long double b) { return a - b > EPS; }
const int INF = 1e9;
const int64_t INF64 = 2e18;
class HLD {
 public:
  V<V<int> > paths;
  V<int> nodeToPath;
  V<int> nodeInPath;
  V<int> parents;
  void build(V<V<int> > &graph) {
    int size = graph.size();
    V<int> sizes(size);
    calc_subtree_sizes(graph, sizes, 0, 0);
    nodeToPath.resize(size);
    nodeInPath.resize(size);
    paths.push_back({});
    build(graph, sizes, 0, 0, 0);
    parents.resize(size);
    build_parents(graph, 0, -1);
  }
  void build(V<V<int> > &graph, V<int> &sizes, int iPath, int node, int prev) {
    paths[iPath].push_back(node);
    nodeToPath[node] = iPath;
    nodeInPath[node] = paths[iPath].size() - 1;
    int maxChild = -1;
    int maxChildSize = 0;
    for (auto &child : graph[node]) {
      if (child != prev) {
        if (sizes[child] > maxChildSize) {
          maxChild = child;
          maxChildSize = sizes[child];
        }
      }
    }
    for (auto &child : graph[node]) {
      if (child != prev) {
        if (child == maxChild) {
          build(graph, sizes, iPath, child, node);
        } else {
          paths.push_back({});
          build(graph, sizes, paths.size() - 1, child, node);
        }
      }
    }
  }
  void build_parents(V<V<int> > &graph, int node, int parent) {
    parents[node] = parent;
    for (auto &child : graph[node]) {
      if (child != parent) {
        build_parents(graph, child, node);
      }
    }
  }
  void calc_subtree_sizes(V<V<int> > &graph, V<int> &sizes, int node,
                          int prev) {
    int size = 1;
    for (auto &child : graph[node]) {
      if (child != prev) {
        calc_subtree_sizes(graph, sizes, child, node);
        size += sizes[child];
      }
    }
    sizes[node] = size;
  }
};
template <class TreeVal>
class SegmentTree {
 public:
  V<TreeVal> t;
  int size;
  void init(int sz) {
    size = sz;
    t.resize(size * 4);
  }
  inline int left(int i) const { return i * 2 + 1; }
  inline int right(int i) const { return i * 2 + 2; }
};
struct Node {
  int n = 1;
  int v = 0;
  int totalN = 1;
  int totalV = 0;
};
struct Update {
  int mulN = 1;
  int addV = 0;
  void reset() {
    mulN = 1;
    addV = 0;
  }
  void add(const Update &u) { add(u.addV, u.mulN); }
  void add(int v, int n) {
    addV = ADD_MOD(addV, MUL_MOD(mulN, v));
    mulN = MUL_MOD(mulN, n);
  }
};
class PathQuery : SegmentTree<Update> {
 public:
  V<Node> a;
  void init(int sz) {
    SegmentTree::init(sz);
    a.resize(sz);
  }
  void update_node(Node &n, Update &u) {
    n.totalV = ADD_MOD(n.totalV, MUL_MOD(u.addV, MUL_MOD(n.n, n.totalN)));
    n.totalN = MUL_MOD(n.totalN, u.mulN);
  }
  void update(int l, int r, int addV, int mulN) {
    update(0, 0, size - 1, l, r, addV, mulN);
  }
  void update(int ti, int sl, int sr, int l, int r, int addV, int mulN) {
    if (sl == l && sr == r) {
      t[ti].add(addV, mulN);
    } else if (l <= r) {
      int m = (sl + sr) / 2;
      update(left(ti), sl, m, l, min(m, r), addV, mulN);
      update(right(ti), m + 1, sr, max(m + 1, l), r, addV, mulN);
    }
  }
  void push_update(int i) { push_update(0, 0, size - 1, i); }
  void push_update(int ti, int sl, int sr, int i) {
    if (sl == sr) {
      update_node(a[i], t[ti]);
      t[ti].reset();
    } else {
      int tl = left(ti);
      int tr = right(ti);
      t[tl].add(t[ti]);
      t[tr].add(t[ti]);
      t[ti].reset();
      int m = (sl + sr) / 2;
      if (i <= m) {
        push_update(tl, sl, m, i);
      } else {
        push_update(tr, m + 1, sr, i);
      }
    }
  }
};
struct Request {
  int type;
  int node;
  int val;
};
HLD hld;
V<PathQuery> pathQueries;
void init_node(int node, int v) {
  int path = hld.nodeToPath[node];
  int iPath = hld.nodeInPath[node];
  auto &val = pathQueries[path].a[iPath];
  val.v = val.totalV = v;
}
void float_update(int node, int v) {
  int path = hld.nodeToPath[node];
  int iPath = hld.nodeInPath[node];
  auto &pathQ = pathQueries[path];
  pathQ.push_update(iPath);
  v = DIV_MOD(v, pathQ.a[iPath].totalN);
  pathQ.update(0, iPath, v, 1);
  pathQ.push_update(0);
  v = MUL_MOD(v, MUL_MOD(pathQ.a[0].totalN, pathQ.a[0].n));
  int parent = hld.parents[hld.paths[path][0]];
  if (parent >= 0) {
    float_update(parent, v);
  }
}
void add_child(int node, int childV) {
  int path = hld.nodeToPath[node];
  int iPath = hld.nodeInPath[node];
  auto &p = pathQueries[path];
  p.push_update(iPath);
  auto &val = p.a[iPath];
  int dN = DIV_MOD(val.n + 1, val.n);
  val.n++;
  int dV = ADD_MOD(MUL_MOD(val.n, childV), DIV_MOD(val.totalV, val.n - 1));
  val.totalV = ADD_MOD(val.totalV, dV);
  if (iPath > 0) {
    p.update(0, iPath - 1, 0, dN);
  }
  int parent = hld.parents[node];
  if (parent >= 0) {
    float_update(parent, dV);
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.precision(15);
  int v0, q;
  cin >> v0 >> q;
  V<Request> requests(q + 1);
  requests[0].type = 1;
  requests[0].node = 0;
  requests[0].val = v0;
  V<V<int> > graph(1);
  for (int i = 1; i <= q; ++i) {
    auto &r = requests[i];
    cin >> r.type >> r.node;
    --r.node;
    if (r.type == 1) {
      cin >> r.val;
      int parent = r.node;
      r.node = graph.size();
      graph.push_back(V<int>());
      graph[parent].push_back(r.node);
      graph[r.node].push_back(parent);
    }
  }
  hld.build(graph);
  int pathCount = hld.paths.size();
  pathQueries.resize(pathCount);
  for (int i = 0; i < pathCount; ++i) {
    pathQueries[i].init(hld.paths[i].size());
  }
  for (int i = 0; i <= q; ++i) {
    auto &r = requests[i];
    if (r.type == 1) {
      init_node(r.node, r.val);
      int parent = hld.parents[r.node];
      if (parent >= 0) {
        add_child(parent, r.val);
      }
    } else {
      int path = hld.nodeToPath[r.node];
      int node = hld.nodeInPath[r.node];
      auto &query = pathQueries[path];
      query.push_update(node);
      cout << query.a[node].totalV << endl;
    }
  }
  return 0;
}
