This function is now way less important than it was when the language was still dynamically typed. But ok to leave it as-is for "index out of range" and other errors that are still dynamic.
| 288 | // This function is now way less important than it was when the language was still dynamically |
| 289 | // typed. But ok to leave it as-is for "index out of range" and other errors that are still dynamic. |
| 290 | Value VM::Error(string err, const RefObj *a, const RefObj *b) { |
| 291 | if (trace == TraceMode::TAIL && trace_output.size()) { |
| 292 | string s; |
| 293 | for (size_t i = trace_ring_idx; i < trace_output.size(); i++) s += trace_output[i].str(); |
| 294 | for (size_t i = 0; i < trace_ring_idx; i++) s += trace_output[i].str(); |
| 295 | s += err; |
| 296 | THROW_OR_ABORT(s); |
| 297 | } |
| 298 | ostringstream ss; |
| 299 | #ifndef VM_COMPILED_CODE_MODE |
| 300 | DumpFileLine(ip, ss); |
| 301 | ss << ": "; |
| 302 | #endif |
| 303 | ss << "VM error: " << err; |
| 304 | if (a) { ss << "\n arg: "; RefToString(*this, ss, a, debugpp); } |
| 305 | if (b) { ss << "\n arg: "; RefToString(*this, ss, b, debugpp); } |
| 306 | while (sp >= 0 && (!stackframes.size() || sp != stackframes.back().spstart)) { |
| 307 | // Sadly can't print this properly. |
| 308 | ss << "\n stack: "; |
| 309 | to_string_hex(ss, (size_t)VM_TOP().any()); |
| 310 | if (pool.pointer_is_in_allocator(VM_TOP().any())) { |
| 311 | ss << ", maybe: "; |
| 312 | RefToString(*this, ss, VM_TOP().ref(), debugpp); |
| 313 | } |
| 314 | VM_POP(); // We don't DEC here, as we can't know what type it is. |
| 315 | // This is ok, as we ignore leaks in case of an error anyway. |
| 316 | } |
| 317 | for (;;) { |
| 318 | if (!stackframes.size()) break; |
| 319 | int deffun = *(stackframes.back().funstart); |
| 320 | if (deffun >= 0) { |
| 321 | ss << "\nin function: " << bcf->functions()->Get(deffun)->name()->string_view(); |
| 322 | } else { |
| 323 | ss << "\nin block"; |
| 324 | } |
| 325 | #ifndef VM_COMPILED_CODE_MODE |
| 326 | ss << " -> "; |
| 327 | DumpFileLine(ip, ss); |
| 328 | #endif |
| 329 | VarCleanup<1>(ss.tellp() < 10000 ? &ss : nullptr, -2 /* clean up temps always */); |
| 330 | } |
| 331 | ss << "\nglobals:"; |
| 332 | for (size_t i = 0; i < bcf->specidents()->size(); ) { |
| 333 | i += DumpVar(ss, vars[i], i, true); |
| 334 | } |
| 335 | THROW_OR_ABORT(ss.str()); |
| 336 | } |
| 337 | |
| 338 | void VM::VMAssert(const char *what) { |
| 339 | Error(string("VM internal assertion failure: ") + what); |
no test coverage detected