#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
const int mod = 1000000007;
int n, q;
int V[N];
vector<int> g[N];
int deg[N];
int npos, pos[N], subtree[N];
struct Query {
  int op;
  int u, v;
} query[N];
struct SegTree {
  int val[N << 2];
  int lazy[N << 2];
  void Build(int L, int R, int rt) {
    val[rt] = 0;
    lazy[rt] = 1;
    if (L == R) return;
    int mid = (L + R) >> 1;
    Build(L, mid, rt << 1);
    Build(mid + 1, R, rt << 1 | 1);
  }
  void LazyDown(int rt) {
    if (lazy[rt] == 1) return;
    lazy[rt << 1] = 1LL * lazy[rt << 1] * lazy[rt] % mod;
    lazy[rt << 1 | 1] = 1LL * lazy[rt << 1 | 1] * lazy[rt] % mod;
    val[rt << 1] = 1LL * val[rt << 1] * lazy[rt] % mod;
    val[rt << 1 | 1] = 1LL * val[rt << 1 | 1] * lazy[rt] % mod;
    lazy[rt] = 1;
  }
  void SumUp(int rt) { val[rt] = (val[rt << 1] + val[rt << 1 | 1]) % mod; }
  void Mul(int l, int r, int c, int L, int R, int rt) {
    if (l <= L && R <= r) {
      val[rt] = 1LL * val[rt] * c % mod;
      lazy[rt] = 1LL * lazy[rt] * c % mod;
      return;
    }
    LazyDown(rt);
    int mid = (L + R) >> 1;
    if (l <= mid) {
      Mul(l, r, c, L, mid, rt << 1);
    }
    if (r > mid) {
      Mul(l, r, c, mid + 1, R, rt << 1 | 1);
    }
    SumUp(rt);
  }
  void Set(int k, int c, int L, int R, int rt) {
    if (L == R) {
      val[rt] = c;
      return;
    }
    LazyDown(rt);
    int mid = (L + R) >> 1;
    if (k <= mid) {
      Set(k, c, L, mid, rt << 1);
    } else {
      Set(k, c, mid + 1, R, rt << 1 | 1);
    }
    SumUp(rt);
  }
  int Query(int l, int r, int L, int R, int rt) {
    if (l <= L && R <= r) {
      return val[rt];
    }
    LazyDown(rt);
    int mid = (L + R) >> 1;
    int ret = 0;
    if (l <= mid) {
      ret += Query(l, r, L, mid, rt << 1);
    }
    if (r > mid) {
      ret += Query(l, r, mid + 1, R, rt << 1 | 1);
    }
    return ret % mod;
  }
} seg;
void Init() {
  npos = 0;
  g[1].clear();
  n = 1;
}
void Input() {
  int c;
  for (int i = 1; i <= q; i++) {
    scanf("%d", &query[i].op);
    if (query[i].op == 1) {
      scanf("%d%d", &query[i].u, &c);
      query[i].v = ++n;
      V[n] = c;
      g[query[i].u].push_back(query[i].v);
      g[query[i].v].clear();
    } else {
      scanf("%d", &query[i].u);
    }
  }
}
void GetPos(int u) {
  pos[u] = ++npos;
  subtree[u] = pos[u];
  for (int i = 0; i < g[u].size(); i++) {
    int v = g[u][i];
    GetPos(v);
    subtree[u] = max(subtree[u], subtree[v]);
  }
}
long long __exgcd(long long a, long long b, long long &x, long long &y) {
  if (b == 0) {
    x = 1;
    y = 1;
    return a;
  }
  long long r = __exgcd(b, a % b, x, y);
  long long t = x;
  x = y;
  y = t - a / b * y;
  return r;
}
int exgcd(int a, int b) {
  long long x, y;
  __exgcd(a, b, x, y);
  x = (x % mod + mod) % mod;
  return (int)x;
}
void DoQuery() {
  seg.Build(1, n, 1);
  seg.Set(pos[1], V[1], 1, n, 1);
  deg[1] = 1;
  for (int i = 1; i <= q; i++) {
    if (query[i].op == 1) {
      int u = query[i].u;
      int v = query[i].v;
      int m = seg.Query(pos[u], pos[u], 1, n, 1);
      m = 1LL * m * exgcd(V[u], mod) % mod * V[v] % mod;
      seg.Set(pos[v], m, 1, n, 1);
      deg[v] = 1;
      m = 1LL * exgcd(deg[u], mod) * (deg[u] + 1) % mod;
      seg.Mul(pos[u], subtree[u], m, 1, n, 1);
      ++deg[u];
    } else {
      int u = query[i].u;
      int m = seg.Query(pos[u], pos[u], 1, n, 1);
      m = 1LL * m * exgcd(V[u], mod) % mod;
      m = 1LL * m * exgcd(deg[u], mod) % mod;
      m = 1LL * seg.Query(pos[u], subtree[u], 1, n, 1) * exgcd(m, mod) % mod;
      printf("%d\n", m);
    }
  }
}
int main() {
  while (cin >> V[1] >> q) {
    Init();
    Input();
    GetPos(1);
    DoQuery();
  }
  return 0;
}
