time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

frameStack.ts (2085B)


      1 // This is called "frameStack" and not "callStack", because the last frame in errors is often not a function call.
      2 // A "frame" is a pair of a scope (function or top-level scope, currently stored as a string) and a location inside it.
      3 // See this comment to deconfuse about what a frame is: https://github.com/quantified-uncertainty/squiggle/pull/1172#issuecomment-1264115038
      4 
      5 import { LocationRange } from "peggy";
      6 
      7 export const topFrameName = "<top>";
      8 
      9 export class Frame {
     10   // Weird hack: without this, Frame class won't be a separate type from the plain JS Object type, since it doesn't have any meaningful methods.
     11   // This could lead to bugs.
     12   isFrame() {
     13     return 1;
     14   }
     15 
     16   constructor(
     17     public name: string,
     18     public location?: LocationRange // can be empty for calls from builtin functions, or for the top frame
     19   ) {}
     20 
     21   toString() {
     22     return (
     23       this.name +
     24       (this.location
     25         ? ` at line ${this.location.start.line}, column ${this.location.start.column}, file ${this.location.source}`
     26         : "")
     27     );
     28   }
     29 }
     30 
     31 export class FrameStack {
     32   constructor(
     33     public frame: Frame,
     34     public parent?: FrameStack
     35   ) {}
     36 
     37   static make(): FrameStack {
     38     return new FrameStack(new Frame("<root>")); // this top frame is always invisible
     39   }
     40 
     41   extend(name: string, location?: LocationRange): FrameStack {
     42     return new FrameStack(new Frame(name, location), this);
     43   }
     44 
     45   // this includes the left offset because it's mostly used in SqError.toStringWithStackTrace
     46   toString(): string {
     47     return this.toFrameArray()
     48       .map((f) => "  " + f.toString())
     49       .join("\n");
     50   }
     51 
     52   toFrameArray(): Frame[] {
     53     const result: Frame[] = [];
     54     let t: FrameStack = this;
     55     while (t && t.frame) {
     56       if (!t.parent) break; // top level frame is fake and should be skipped
     57       result.push(t.frame);
     58       t = t.parent;
     59     }
     60     return result;
     61   }
     62 
     63   getTopFrame(): Frame | undefined {
     64     return this.parent ? this.frame : undefined; // top level frame is always invisible
     65   }
     66 
     67   isEmpty(): boolean {
     68     return this.parent === undefined;
     69   }
     70 }