1. my class CallFrame {
  2. has $.annotations;
  3. has $.my;
  4. method SET-SELF(\level, Mu \ctx is raw, Mu \bt is raw) {
  5. nqp::stmts(
  6. (my int $i = nqp::add_i(level,1)),
  7. ($!annotations := nqp::atkey(
  8. nqp::atpos(nqp::getattr(bt,List,'$!reified'),$i),
  9. 'annotations'
  10. )),
  11. (my $ctx := ctx),
  12. nqp::while(
  13. nqp::isgt_i(($i = nqp::sub_i($i,1)),0),
  14. nqp::ifnull(
  15. ($ctx := nqp::ctxcaller($ctx)),
  16. fail "No callframe at level {level}"
  17. )
  18. ),
  19. ($!my :=
  20. nqp::p6bindattrinvres(nqp::create(Stash),Map,'$!storage',$ctx)),
  21. self
  22. )
  23. }
  24. only method new(CallFrame: Int:D $level = 0) { # MUST BE AN only
  25. nqp::create(CallFrame).SET-SELF( # wrt to backtrace levels
  26. $level,
  27. nqp::ctxcaller(nqp::ctx),
  28. nqp::backtrace(nqp::handle(nqp::die(''),'CATCH',nqp::exception))
  29. )
  30. }
  31. method line() { nqp::atkey($!annotations,'line') }
  32. method file() { nqp::atkey($!annotations,'file') }
  33. method code() {
  34. my \vm-code = nqp::ctxcode(nqp::getattr($!my,Map,'$!storage'));
  35. nqp::isnull(vm-code) ?? Nil !! nqp::getcodeobj(vm-code)
  36. }
  37. method callframe(Int:D $?) {
  38. X::NYI.new(feature => 'Callframe.callframe').throw;
  39. }
  40. multi method gist(CallFrame:D:) {
  41. nqp::atkey($!annotations,'file')
  42. ~ ' at line '
  43. ~ nqp::atkey($!annotations,'line')
  44. }
  45. method annotations() {
  46. nqp::p6bindattrinvres(nqp::create(Map),Map,'$!storage',$!annotations)
  47. }
  48. }
  49. only sub callframe(Int:D $level = 0) { # MUST BE an only wrt to backtrace levels
  50. nqp::create(CallFrame).SET-SELF(
  51. $level,
  52. nqp::ctxcaller(nqp::ctx),
  53. nqp::backtrace(nqp::handle(nqp::die(''),'CATCH',nqp::exception))
  54. )
  55. }