develooper Front page | perl.cvs.parrot | Postings from January 2009

[svn:parrot] r35011 - in branches/bcanno/src: . pmc

From:
jonathan
Date:
January 5, 2009 16:15
Subject:
[svn:parrot] r35011 - in branches/bcanno/src: . pmc
Message ID:
20090106001521.44EA1CBC33@x12.develooper.com
Author: jonathan
Date: Mon Jan  5 16:15:19 2009
New Revision: 35011

Modified:
   branches/bcanno/src/packfile.c
   branches/bcanno/src/pmc/exception.pmc

Log:
[core] Make looking up bytecode annotations in effect at the point an exception was thrown work.

Modified: branches/bcanno/src/packfile.c
==============================================================================
--- branches/bcanno/src/packfile.c	(original)
+++ branches/bcanno/src/packfile.c	Mon Jan  5 16:15:19 2009
@@ -3863,7 +3863,7 @@
         int add) {
     /* Allocate annotations structure; create it all zeroed, and we will
      * allocate memory for each of the arrays on demand. */
-    PackFile_Annotations *seg = mem_allocate_typed(PackFile_Annotations);
+    PackFile_Annotations *seg = mem_allocate_zeroed_typed(PackFile_Annotations);
     return (PackFile_Segment *) seg;
 }
 
@@ -4130,18 +4130,18 @@
 void PackFile_Annotations_add_entry(PARROT_INTERP, struct PackFile_Annotations *self,
         opcode_t offset, opcode_t key, opcode_t type, opcode_t value) {
     INTVAL i;
-    opcode_t key_id = 0;
+    opcode_t key_id = -1;
 
     /* See if we already have this key. */
     STRING *key_name = PF_CONST(self->code, key)->u.string;
     for (i = 0; i < self->num_keys; i++) {
         STRING *test_key = PF_CONST(self->code, self->keys[i]->name)->u.string;
         if (string_equal(interp, test_key, key_name) == 0) {
-            key_id = 0;
+            key_id = i;
             break;
         }
     }
-    if (key_id == 0) {
+    if (key_id == -1) {
         /* We do nee have it. Add key entry. */
         if (self->keys)
             self->keys = mem_sys_realloc(self->keys, (1 + self->num_keys) *
@@ -4180,6 +4180,131 @@
 
 /*
 
+=item C<static PMC * make_annotation_value_pmc>
+
+Helper for PackFile_Annotations_lookup that makes a PMC of the right type
+holding the value.
+
+=cut
+
+*/
+
+static PMC * make_annotation_value_pmc(PARROT_INTERP, struct PackFile_Annotations *self,
+        INTVAL type, opcode_t value) {
+    PMC *result;
+    switch (type) {
+        case PF_ANNOTATION_KEY_TYPE_INT:
+            result = pmc_new(interp, enum_class_Integer);
+            VTABLE_set_integer_native(interp, result, value);
+            break;
+        case PF_ANNOTATION_KEY_TYPE_NUM:
+            result = pmc_new(interp, enum_class_Float);
+            VTABLE_set_number_native(interp, result,
+                    PF_CONST(self->code, value)->u.number);
+            break;
+        default:
+            result = pmc_new(interp, enum_class_String);
+            VTABLE_set_string_native(interp, result,
+                    PF_CONST(self->code, value)->u.string);
+    }
+    return result;
+}
+
+
+/*
+
+=item C<PMC * PackFile_Annotations_lookup>
+
+Looks up the annotation(s) in force at the given bytecode offset. If just one
+particular annotation is required, it can be passed as key, and the value will
+be returned (or a NULL PMC if no annotation of that name is in force). Otherwise,
+a Hash will be returned of the all annotations. If there are none in force, an
+empty hash will be returned.
+
+=cut
+
+*/
+
+PMC * PackFile_Annotations_lookup(PARROT_INTERP, struct PackFile_Annotations *self,
+        opcode_t offset, STRING *key) {
+    INTVAL i;
+    INTVAL start_entry = 0;
+    PMC *  result;
+
+    /* If we have a key, look up its ID; if we don't find one. */
+    opcode_t key_id = -1;
+    if (key != NULL) {
+        for (i = 0; i < self->num_keys; i++) {
+            STRING *test_key = PF_CONST(self->code, self->keys[i]->name)->u.string;
+            if (string_equal(interp, test_key, key) == 0) {
+                key_id = i;
+                break;
+            }
+        }
+        if (key_id == -1)
+            return PMCNULL;
+    }
+
+    /* Use groups to find search start point. */
+    for (i = 0; i < self->num_groups; i++)
+        if (offset < self->groups[i]->bytecode_offset)
+            break;
+        else
+            start_entry = self->groups[i]->entries_offset;
+    
+    if (key_id == -1) {
+        /* Look through entries, storing what we find by key and tracking those
+         * that we have values for. */
+        opcode_t *latest_values = mem_allocate_n_zeroed_typed(self->num_keys, opcode_t);
+        opcode_t *have_values   = mem_allocate_n_zeroed_typed(self->num_keys, opcode_t);
+        for (i = start_entry; i < self->num_entries; i++) {
+            if (self->entries[i]->bytecode_offset >= offset)
+                break;
+            latest_values[self->entries[i]->key] = self->entries[i]->value;
+            have_values[self->entries[i]->key]   = 1;
+        }
+
+        /* Create hash of values we have. */
+        result = pmc_new(interp, enum_class_Hash);
+        for (i = 0; i < self->num_keys; i++) {
+            if (have_values[i]) {
+                STRING *key_name = PF_CONST(self->code, self->keys[i]->name)->u.string;
+                VTABLE_set_pmc_keyed_str(interp, result, key_name,
+                        make_annotation_value_pmc(interp, self, self->keys[i]->type,
+                                latest_values[i]));
+            }
+        }
+
+        mem_sys_free(latest_values);
+        mem_sys_free(have_values);
+    }
+    else {
+        /* Look for latest applicable value of the key. */
+        opcode_t latest_value = 0;
+        opcode_t found_value  = 0;
+        for (i = start_entry; i < self->num_entries; i++) {
+            if (self->entries[i]->bytecode_offset >= offset)
+                break;
+            if (self->entries[i]->key == key_id) {
+                latest_value = self->entries[i]->value;
+                found_value  = 1;
+            }
+        }
+
+        /* Did we find anything? */
+        if (!found_value)
+            result = PMCNULL;
+        else
+            result = make_annotation_value_pmc(interp, self,
+                    self->keys[key_id]->type, latest_value);
+    }
+
+    return result;
+}
+
+
+/*
+
 =item C<static PackFile * PackFile_append_pbc>
 
 Read a PBC and append it to the current directory

Modified: branches/bcanno/src/pmc/exception.pmc
==============================================================================
--- branches/bcanno/src/pmc/exception.pmc	(original)
+++ branches/bcanno/src/pmc/exception.pmc	Mon Jan  5 16:15:19 2009
@@ -695,6 +695,40 @@
         return shared_self;
     }
 
+
+/*
+
+=item C<PMC *annotations>
+
+Gets any bytecode annotations in force at the point where the exception was
+thrown. If the optional name of an annotation is specified, gets just that
+annotation. If not, returns a Hash of all of them.
+
+=cut
+
+*/
+
+    METHOD PMC *annotations(STRING *name :optional, INTVAL have_name :opt_flag) {
+        PMC *resume;
+        PMC *result = PMCNULL;
+
+        /* Get resume continuation, to find location we failed at. */
+        GET_ATTR_resume(interp, SELF, resume);
+        if (!PMC_IS_NULL(resume)) {
+            Parrot_cont *cont = PMC_cont(resume);
+            if (cont->seg != NULL && cont->seg->annotations != NULL)
+                result = PackFile_Annotations_lookup(interp, cont->seg->annotations,
+                        cont->address - cont->seg->base.data, name);
+        }
+
+        /* If we didn't have a key specified and we found no annotations to
+         * return, should return an empty hash. */
+        if (!have_name && PMC_IS_NULL(result))
+            result = pmc_new(interp, enum_class_Hash);
+
+        RETURN(PMC *result);
+    }
+
 /*
 
 =back



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About