3.21. kink/TRACE

The companion mod for trace vals.

3.21.1. type trace

A trace val is an element of a stack trace.

A trace val consists of the following components. Both are optional.

• sym: a str val; usually the sym of the called fun.

• loc: a loc val; usually the loc where the invocation occurred.

Trace.snip?

`snip?` returns whether the `Trace` is a SNIP trace, which does not have a sym nor a loc, and it is of a tail trace.

Trace.have_sym?

`have_sym?` returns whether the `Trace` has a sym.

Trace.sym

`sym` returns the sym of the `Trace`.

Precondition:

• `Trace` must have a sym

Trace.have_loc?

`have_loc?` returns whether the `Trace` has a loc.

Trace.loc

`loc` returns the loc of the `Trace`.

Precondition:

• `Trace` must have a loc.

Trace.tail?

`tail?` returns whether the `Trace` is of a tail-call.

Trace1.op_eq(Trace2)

`op_eq` returns whether the two traces are equal.

Two traces are equal when and only when the following calculated properties of the traces are equal.

• `if(T.have_sym? { [T.sym] } { []})`

• `if(T.have_loc? { [T.loc] } { []})`

• `T.tail?`

Trace.desc

`desc` returns a str which describes the `Trace`.

Example:

:LOC.require_from('kink/')
:TRACE.require_from('kink/')

:Loc <- LOC.new('foo.kn' 'foo(bar)' 4)

stdout.print_line(TRACE.new{(:T) T.sym('bar') T.loc(Loc) }.desc.repr)
# => "[foo.kn L1 C5 bar] foo(-->bar)"

stdout.print_line(TRACE.new{(:T) T.sym('bar') }.desc.repr)
# => "[bar]"

stdout.print_line(TRACE.new{(:T) T.sym('bar') T.on_tail }.desc.repr)
# => "{bar}"

stdout.print_line(TRACE.new{(:T) T.loc(Loc) }.desc.repr)
# => "[foo.kn L1 C5] foo(-->bar)"

stdout.print_line(TRACE.snip.desc.repr)
# => "{..snip..}"

stdout.print_line(TRACE.new{}.desc.repr)
# => "[..empty..]"

If the `Trace` is of a tail call, the first part is enclosed by "{...}". If the `Trace` is not of a tail call, the first part is enclosed by "[...]".

3.21.2. TRACE.is?(Val)

`is?` returns whether the `Val` is a trace val.

3.21.3. TRACE.snip

`snip` returns the snip trace, which is equal to `TRACE.new{(:C) C.on_tail }`.

3.21.4. TRACE.new(...[$config = {}])

`new` makes a trace.

$config is called with a `Conf`, to configure the trace.

The `Conf` has two methods.

• Conf.sym(Sym) : gives the sym of the trace.

• Conf.loc(Loc) : gives the loc of the trace.

• Conf.on_tail : the trace is of a tail-call.

Example:

:TRACE.require_from('kink/')
:LOC.require_from('kink/')
:Trace <- TRACE.new{(:T)
  T.sym('op_add')
  T.loc(LOC.new('foo.kn' '10+20' 2))
}
stdout.print_line(Trace.repr) # => (trace op_add (loc foo.kn L1 C3) tail?=false)

3.21.5. TRACE.format_traces(Msg Traces)

`format_traces` returns an iter of lines describing `Msg` and `Traces` of an exception.

Preconditions:

• `Msg` must be a str val

• `Traces` must be a vec of traces

Example:

:TRACE.require_from('kink/')
:CONTROL.require_from('kink/')

CONTROL.try(
  { 10 / 0 }
  {(:R) raise('must not reach here') }
  {(:Msg :Traces)
    TRACE.format_traces(Msg Traces).each{(:Line)
      stdout.print_line(Line)
    }
  }
)
# Output:
#   exception traces: from oldest to newest
#   {startup}
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L236 C3 _startup_aux} -->_startup_aux(Args Dep)
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L219 C11 try} CONTROL.-->try(
#   [builtin:kink-mods/kink/CONTROL.kn L207 C19 reset] :handler = KONT.-->reset('kink/CONTROL-try'){
#   [builtin:kink-mods/kink/CONTROL.kn L208 C10 body] :R = -->body
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L221 C7 _start} -->_start(Non_opts Dep)
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L122 C3 if} -->if(Non_opts.empty?
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L135 C7 branch} -->branch(
#   {builtin:kink-mods/kink/_startup/STARTUP.kn L160 C11 _run_script} -->_run_script($script_fun Script_args)
#   [builtin:kink-mods/kink/_startup/STARTUP.kn L113 C3 script_fun] -->script_fun(Binding)
#   {(stdin) L4 C9 try} CONTROL.-->try(
#   [builtin:kink-mods/kink/CONTROL.kn L207 C19 reset] :handler = KONT.-->reset('kink/CONTROL-try'){
#   [builtin:kink-mods/kink/CONTROL.kn L208 C10 body] :R = -->body
#   {(stdin) L5 C8 op_div} { 10 -->/ 0 }
#   exception message: Num.op_div: zero division: 10 is divided by 0