[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