[svn:parrot] r41554 - in trunk: src/pmc t/pmc
bacek at svn.parrot.org
bacek at svn.parrot.org
Tue Sep 29 12:25:38 UTC 2009
Author: bacek
Date: Tue Sep 29 12:25:37 2009
New Revision: 41554
URL: https://trac.parrot.org/parrot/changeset/41554
Log:
[core] Implement Context.backtrace
Modified:
trunk/src/pmc/context.pmc
trunk/t/pmc/context.t
Modified: trunk/src/pmc/context.pmc
==============================================================================
--- trunk/src/pmc/context.pmc Tue Sep 29 12:00:14 2009 (r41553)
+++ trunk/src/pmc/context.pmc Tue Sep 29 12:25:37 2009 (r41554)
@@ -21,6 +21,7 @@
#include "parrot/packfile.h"
+#include "pmc_sub.h"
pmclass Context {
@@ -189,6 +190,68 @@
return STATICSELF.get_pmc_keyed_str(VTABLE_get_string(INTERP, key));
}
+/*
+
+=item C<PMC *backtrace>
+
+Gets a representation of the backtrace starting from this Context.
+Returns an array of hashes. Each array element represents a caller in
+the backtrace, the most recent caller first. The hash has two keys: C<sub>,
+which holds the PMC representing the sub, and C<annotations> which is a hash
+of the annotations at the point where the exception was thrown for the current
+sub, or for the point of the call a level deeper for the rest.
+
+=cut
+
+XXX Stolen from Exception.backtrace. Only one difference in handling C<cont>
+TODO Investigate and implement Exception.backtrace in terms of Context.backtrace.
+
+*/
+
+ METHOD backtrace() {
+ PMC *result = pmc_new(interp, enum_class_ResizablePMCArray);
+ PMC *cur_ctx = SELF;
+
+ /* Get starting context, then loop over them. */
+ while (cur_ctx) {
+ PMC *frame = pmc_new(interp, enum_class_Hash);
+ PMC *annotations = NULL;
+ Parrot_Sub_attributes *sub;
+
+ /* Get sub and put it in the hash. */
+ PMC *sub_pmc = Parrot_pcc_get_sub(interp, cur_ctx);
+
+ if (!sub_pmc)
+ sub_pmc = PMCNULL;
+
+ VTABLE_set_pmc_keyed_str(interp, frame, CONST_STRING(interp, "sub"), sub_pmc);
+
+ /* Look up any annotations and put them in the hash. */
+ if (!PMC_IS_NULL(sub_pmc)) {
+ PMC_get_sub(interp, sub_pmc, sub);
+
+ if (sub->seg->annotations) {
+ PackFile_ByteCode *seg = sub->seg;
+ opcode_t *pc = Parrot_pcc_get_pc(interp, cur_ctx);
+
+ annotations = PackFile_Annotations_lookup(interp,
+ seg->annotations, pc - seg->base.data,
+ NULL);
+ }
+ }
+
+ if (!annotations)
+ annotations = pmc_new(interp, enum_class_Hash);
+
+ VTABLE_set_pmc_keyed_str(interp, frame, CONST_STRING(interp, "annotations"), annotations);
+
+ /* Push frame and go to next caller. */
+ VTABLE_push_pmc(interp, result, frame);
+ cur_ctx = Parrot_pcc_get_caller_ctx(interp, cur_ctx);
+ }
+
+ RETURN(PMC *result);
+ }
}
/*
Modified: trunk/t/pmc/context.t
==============================================================================
--- trunk/t/pmc/context.t Tue Sep 29 12:00:14 2009 (r41553)
+++ trunk/t/pmc/context.t Tue Sep 29 12:25:37 2009 (r41554)
@@ -23,15 +23,16 @@
.sub main :main
.include 'test_more.pir'
- plan(16)
+ plan(19)
test_new()
$P0 = get_hll_global ['Foo'], 'load'
$P0()
$P0 = new ['Foo']
- $P0.'test_inspect'()
+ $P0.'test_inspect'() # 15 tests
+ test_backtrace() # 3 tests
.end
.sub 'test_new'
@@ -126,6 +127,37 @@
.end
+.namespace []
+
+.sub 'test_backtrace'
+ .local pmc bt
+ bt = 'test_bt1'()
+ $I0 = defined bt
+ ok($I0, "Got Context.backtrace()")
+
+ # We should have more than 3 elements
+ $I0 = elements bt
+ $I1 = $I0 > 3
+ ok($I1, "... got enough elements")
+
+ # First one should be "test_bt2"
+ $P1 = shift bt
+ $P2 = $P1['sub']
+ is($P2, 'test_bt2', "... with correct first element")
+.end
+
+.sub 'test_bt1'
+ $P0 = 'test_bt2'()
+ .return ($P0)
+.end
+
+.sub 'test_bt2'
+ $P0 = getinterp
+ $P1 = $P0['context']
+ $P2 = $P1.'backtrace'()
+ .return ($P2)
+.end
+
# Local Variables:
# mode: pir
# fill-column: 100
More information about the parrot-commits
mailing list