(Break.JaM.. ) .print (/breakdepth) (Returns level of nesting inside break points) ( (:breakdepth) .lvknown (:breakdepth) .cvx 0 .ifelse ) /xdef (/breakexpr) (Returns current break expression if any) ( (:breakexpr) .lvknown (:breakexpr) .cvx (()) .cvx .ifelse) /xdef (/breakname) (Returns current break name if any) ( (:breakname) .lvknown (:breakname) .cvx (()) .cvx .ifelse) /xdef (/breakcoms) (Returns current break commands if any) ( (:breakcoms) .lvknown (:breakcoms) .cvx (()) .cvx .ifelse) /xdef (/breaktest) (Returns current break test if any) ( (:breaktest) .lvknown (:breaktest) .cvx (()) .cvx .ifelse) /xdef (/breakpoint) (Break routine that interacts with the user) ( (:breakdepth) /breakdepth 1 .add .lv (:breakevaled) .false .lv (:breakexpr) .exch .lv (:breakcoms) .exch .lv (:breaktest) .exch .lv (:breakname) .exch .lv :breaktest .cvx .exec ( :breakname (.interrupt) .eq (( interrupt) =) .cvx (( ) .print :breakname .print ( broken) =) .cvx .ifelse :breakcoms ( .cvx .exec :breakdepth 1 .sub (( ) .print) .cvx .rept (>) .print .userline .dup .length 0 .eq (.pop .exit) .cvx .if) .cvx .loop ) .cvx .if :breakevaled .not (/brkeval) .cvx .if) /xdef (/brkgo) (.exit) .cvx .def (/brkskip) ((:breakevaled) .true .lvstore .exit) .cvx .def (/brkeval) ((:breakevaled) .true .lvstore /breakexpr .cvx .exec) .cvx .def (/!brkeval) ( (:breakdef) :breakname .load .lv :breakname :breakexpr .store /brkeval :breakname :breakdef .store ) .cvx .def (/!brkgo) ( /!brkeval /brkgo) .cvx .def (/brkwho) (/breakname) .cvx .def (/unbreak) ( ( (:unbrkwho) .exch .cvlit .lv :unbrkwho /isbroken .not (:unbrkwho .print ( not broken) = .exit) .cvx .if :unbrkwho .load 3 .aget :unbrkwho .exch .store :unbrkwho .print ( unbroken) = .exit) .cvx .loop) .cvx .def (/isbroken) ( (.load .dup .type (.arraytype) .eq .not (.false .exit) .cvx .if .dup .length 5 .eq .not (.false .exit) .cvx .if .dup 4 .aget .type (.stringtype) .eq .not (.false .exit) .cvx .if .dup 4 .aget (/breakpoint) .eq .not (.false .exit) .cvx .if .true .exit) .cvx .loop .exch .pop ) .cvx .def (/break) (Place a breakpoint. Expects function name on operand stack, or array of name, test, and commands) ( (.dup .type (.stringtype) .eq (.true ()) .cvx (.aload .pop) .cvx .ifelse (:brkcoms) .exch .cvlit .lv (:brktest) .exch .cvlit .lv (:brkname) .exch .cvlit .lv (:brkexpr) :brkname .load .cvlit .lv :brkname /isbroken (:brkname .print ( already broken) = .exit) .cvx .if :brkname [ :brkname :brktest :brkcoms :brkexpr (/breakpoint) .cvx ] .cvx .store :brkname .print ( broken) = .exit) .cvx .loop) /xdef (.interrupt) [ (.interrupt) .true () () (/breakpoint) .cvx ] .cvx .def (/bt) (Prints a back trace of the execution stack) ( (:stack) .execstk .cvlit .lv (:loc) 0 .lv :stack .length ( (:item) :stack :loc .aget .cvlit .lv (:typename) :item .type .cvlit .lv :typename (.stringtype) .eq :typename (.arraytype) .eq .or :typename (.inputtype) .eq .or (:item ==) .cvx .if (:loc) :loc 1 .add .lvstore ) .cvx .rept ) /xdef (Done ) .print