import java.io.*; import java.util.*; public class Main_yukicoder510 { private static Scanner sc; private static Printer pr; private static void solve() { int n = sc.nextInt(); nn = 1; while (nn < n) { nn *= 2; } st = new int[2 * nn - 1][][]; for (int i = 0; i < n; i++) { st[i + nn - 1] = setM(Matrix.getI(4), 0, 0); } for (int i = n; i < nn; i++) { st[i + nn - 1] = Matrix.getI(4); } for (int i = nn - 2; i >= 0; i--) { st[i] = Matrix.mul(st[2 * i + 2], st[2 * i + 1]); } int q = sc.nextInt(); for (int k = 0; k < q; k++) { char[] xya = sc.next().toCharArray(); if (xya[0] == 'x') { int i = sc.nextInt(); int v = sc.nextInt(); update(i, v, st[nn - 1 + i][1][1]); } else if (xya[0] == 'y') { int i = sc.nextInt(); int v = sc.nextInt(); update(i, st[nn - 1 + i][0][2], v); } else { int i = sc.nextInt(); if (i == 0) { pr.println(1); } else { int[] a0 = {1, 1, 1, 1}; int[] ans = Matrix.mul(query(0, i), a0); pr.println(ans[0]); } } } } private static int nn; private static int[][][] st; // a, b:0-indexed // [a, b) private static int[][] query(int a, int b) { return query(a, b, 0, 0, nn); } private static int[][] query(int a, int b, int i, int l, int r) { if (a >= r || b <= l) { return Matrix.getI(4); } if (a <= l && b >= r) { return st[i]; } return Matrix.mul(query(a, b, i * 2 + 2, (l + r) / 2, r), query(a, b, i * 2 + 1, l, (l + r) / 2)); } // i:0-indexed private static void update(int i, int x, int y) { i = nn - 1 + i; setM(st[i], x, y); while (i > 0) { i = (i - 1) / 2; st[i] = Matrix.mul(st[2 * i + 2], st[2 * i + 1]); } } private static final int MOD = 1_000_000_007; private static int[][] setM(int[][] ret, int x, int y) { ret[0][2] = x; ret[1][1] = y; ret[1][3] = 1; ret[2][1] = 2 * y % MOD; ret[2][2] = (int)((long)y * y % MOD); ret[2][3] = 1; return ret; } private static class Matrix { static int[] mul(int[][] a, int[] x) { int m = a.length; int n = a[0].length; if (n != x.length) { throw new IllegalArgumentException(); } int[] y = new int[m]; for (int i = 0; i < m; i++) { long tmp = 0; for (int j = 0; j < n; j++) { tmp += (long)a[i][j] * x[j]; tmp %= MOD; } y[i] = (int)tmp; } return y; } static int[][] mul(int[][] a, int[][] a2) { int m = a.length; int n = a2[0].length; int l = a[0].length; if (l != a2.length) { throw new IllegalArgumentException(); } int[][] y = new int[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { long tmp = 0; for (int k = 0; k < l; k++) { tmp += (long)a[i][k] * a2[k][j]; tmp %= MOD; } y[i][j] = (int)tmp; } } return y; } static int[][] getI(int n) { int[][] mat = new int[n][]; for (int i = 0; i < n; i++) { mat[i] = new int[n]; mat[i][i] = 1; } return mat; } } // --------------------------------------------------- public static void main(String[] args) { sc = new Scanner(System.in); pr = new Printer(System.out); solve(); pr.close(); sc.close(); } @SuppressWarnings("unused") private static class Scanner { BufferedReader br; Scanner (InputStream in) { br = new BufferedReader(new InputStreamReader(in)); } private boolean isPrintable(int ch) { return ch >= '!' && ch <= '~'; } private boolean isCRLF(int ch) { return ch == '\n' || ch == '\r' || ch == -1; } private int nextPrintable() { try { int ch; while (!isPrintable(ch = br.read())) { if (ch == -1) { throw new NoSuchElementException(); } } return ch; } catch (IOException e) { throw new NoSuchElementException(); } } String next() { try { int ch = nextPrintable(); StringBuilder sb = new StringBuilder(); do { sb.appendCodePoint(ch); } while (isPrintable(ch = br.read())); return sb.toString(); } catch (IOException e) { throw new NoSuchElementException(); } } int nextInt() { try { // parseInt from Integer.parseInt() boolean negative = false; int res = 0; int limit = -Integer.MAX_VALUE; int radix = 10; int fc = nextPrintable(); if (fc < '0') { if (fc == '-') { negative = true; limit = Integer.MIN_VALUE; } else if (fc != '+') { throw new NumberFormatException(); } fc = br.read(); } int multmin = limit / radix; int ch = fc; do { int digit = ch - '0'; if (digit < 0 || digit >= radix) { throw new NumberFormatException(); } if (res < multmin) { throw new NumberFormatException(); } res *= radix; if (res < limit + digit) { throw new NumberFormatException(); } res -= digit; } while (isPrintable(ch = br.read())); return negative ? res : -res; } catch (IOException e) { throw new NoSuchElementException(); } } long nextLong() { try { // parseLong from Long.parseLong() boolean negative = false; long res = 0; long limit = -Long.MAX_VALUE; int radix = 10; int fc = nextPrintable(); if (fc < '0') { if (fc == '-') { negative = true; limit = Long.MIN_VALUE; } else if (fc != '+') { throw new NumberFormatException(); } fc = br.read(); } long multmin = limit / radix; int ch = fc; do { int digit = ch - '0'; if (digit < 0 || digit >= radix) { throw new NumberFormatException(); } if (res < multmin) { throw new NumberFormatException(); } res *= radix; if (res < limit + digit) { throw new NumberFormatException(); } res -= digit; } while (isPrintable(ch = br.read())); return negative ? res : -res; } catch (IOException e) { throw new NoSuchElementException(); } } float nextFloat() { return Float.parseFloat(next()); } double nextDouble() { return Double.parseDouble(next()); } String nextLine() { try { int ch; while (isCRLF(ch = br.read())) { if (ch == -1) { throw new NoSuchElementException(); } } StringBuilder sb = new StringBuilder(); do { sb.appendCodePoint(ch); } while (!isCRLF(ch = br.read())); return sb.toString(); } catch (IOException e) { throw new NoSuchElementException(); } } void close() { try { br.close(); } catch (IOException e) { // throw new NoSuchElementException(); } } } private static class Printer extends PrintWriter { Printer(PrintStream out) { super(out); } } }