MIRROR: javascript for 🐜's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 201 lines 4.8 kB view raw
1// Reproduce "undeclared reg 0" MIR error: switch statement with many 2// string-constant cases, method calls, and property access — matching 3// the exact bytecode pattern of a TUI handleKey function. 4 5const keys = { 6 UP: '\x1b[A', 7 DOWN: '\x1b[B', 8 RIGHT: '\x1b[C', 9 LEFT: '\x1b[D', 10 PAGE_UP: '\x1b[5~', 11 PAGE_DOWN: '\x1b[6~', 12 ENTER: '\r', 13 ESCAPE: '\x1b', 14 TAB: '\t', 15 BACKSPACE: '\x7f', 16 HOME: '\x1b[H', 17 END: '\x1b[F', 18 CTRL_C: '\x03', 19}; 20 21const list = { 22 index: 0, 23 items: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 24 selectNext() { this.index = Math.min(this.items.length - 1, this.index + 1); }, 25 selectPrev() { this.index = Math.max(0, this.index - 1); }, 26 pageDown() { this.index = Math.min(this.items.length - 1, this.index + 5); }, 27 pageUp() { this.index = Math.max(0, this.index - 5); }, 28 getSelected() { return this.items[this.index]; }, 29}; 30 31const logList = { 32 index: 0, 33 items: ['a', 'b', 'c'], 34 selectNext() { this.index = Math.min(this.items.length - 1, this.index + 1); }, 35 selectPrev() { this.index = Math.max(0, this.index - 1); }, 36 pageDown() { this.index = Math.min(this.items.length - 1, this.index + 5); }, 37 pageUp() { this.index = Math.max(0, this.index - 5); }, 38}; 39 40const state = { 41 view: 'tasks', 42 searchMode: false, 43 searchQuery: '', 44 taskFilter: 'all', 45 settingsIndex: 0, 46}; 47 48let renderCount = 0; 49function render() { renderCount++; } 50 51// Use switch(key) — this generates DUP+CONST+SEQ+JMP_FALSE chains where 52// the discriminant stays on the vstack across branch targets. 53function handleKey(key) { 54 if (state.searchMode) { 55 if (key === keys.ESCAPE) { 56 state.searchMode = false; 57 state.searchQuery = ''; 58 render(); 59 return; 60 } 61 if (key === keys.ENTER) { 62 state.searchMode = false; 63 render(); 64 return; 65 } 66 return; 67 } 68 69 switch (key) { 70 case 'q': 71 case keys.CTRL_C: 72 return; 73 74 case '1': 75 state.view = 'dashboard'; 76 render(); 77 break; 78 case '2': 79 state.view = 'tasks'; 80 render(); 81 break; 82 case '3': 83 state.view = 'logs'; 84 render(); 85 break; 86 case '4': 87 state.view = 'settings'; 88 render(); 89 break; 90 91 case '?': 92 render(); 93 break; 94 case 'm': 95 render(); 96 break; 97 98 case keys.UP: 99 case 'k': 100 if (state.view === 'tasks') list.selectPrev(); 101 else if (state.view === 'logs') logList.selectPrev(); 102 else if (state.view === 'settings') state.settingsIndex = Math.max(0, state.settingsIndex - 1); 103 render(); 104 break; 105 106 case keys.DOWN: 107 case 'j': 108 if (state.view === 'tasks') list.selectNext(); 109 else if (state.view === 'logs') logList.selectNext(); 110 else if (state.view === 'settings') state.settingsIndex = Math.min(9, state.settingsIndex + 1); 111 render(); 112 break; 113 114 case keys.PAGE_UP: 115 if (state.view === 'tasks') list.pageUp(); 116 else if (state.view === 'logs') logList.pageUp(); 117 render(); 118 break; 119 120 case keys.PAGE_DOWN: 121 if (state.view === 'tasks') list.pageDown(); 122 else if (state.view === 'logs') logList.pageDown(); 123 render(); 124 break; 125 126 case keys.ENTER: 127 case keys.RIGHT: 128 if (state.view === 'tasks') { 129 const item = list.getSelected(); 130 if (item) { 131 const desc = 'item_' + String(item); 132 if (desc.length > 0) render(); 133 } 134 } 135 render(); 136 break; 137 138 case keys.LEFT: 139 render(); 140 break; 141 142 case keys.HOME: 143 list.index = 0; 144 render(); 145 break; 146 147 case keys.END: 148 list.index = list.items.length - 1; 149 render(); 150 break; 151 152 case keys.TAB: 153 state.view = 'dashboard'; 154 render(); 155 break; 156 157 case '/': 158 if (state.view === 'tasks') { 159 state.searchMode = true; 160 state.searchQuery = ''; 161 } 162 render(); 163 break; 164 165 case 'a': 166 if (state.view === 'tasks') { state.taskFilter = 'all'; render(); } 167 break; 168 case 't': 169 if (state.view === 'tasks') { state.taskFilter = 'todo'; render(); } 170 break; 171 case 'p': 172 if (state.view === 'tasks') { state.taskFilter = 'in_progress'; render(); } 173 break; 174 case 'd': 175 if (state.view === 'tasks') { state.taskFilter = 'done'; render(); } 176 break; 177 case 'P': 178 render(); 179 break; 180 case 'D': 181 render(); 182 break; 183 case 'N': 184 render(); 185 break; 186 } 187} 188 189const scrollKeys = [ 190 keys.UP, keys.DOWN, keys.UP, keys.DOWN, 191 keys.PAGE_UP, keys.PAGE_DOWN, 192 keys.UP, keys.DOWN, 'k', 'j', 193 keys.ENTER, keys.LEFT, keys.RIGHT, 194 keys.HOME, keys.END, keys.TAB, 195]; 196 197for (let i = 0; i < 500; i++) { 198 handleKey(scrollKeys[i % scrollKeys.length]); 199} 200 201console.log('OK: rendered', renderCount, 'times, list index:', list.index);