Ejemplo n.º 1
0
/* Initializes our cached versions of some strings and type IDs that we
 * use very commonly. For strings, this should mean we only compute their
 * hash value once, rather than every time we create and consume them. */
static void setup_binder_statics(PARROT_INTERP) {
    ACCEPTS          = Parrot_str_new_constant(interp, "ACCEPTS");
    HOW              = Parrot_str_new_constant(interp, "HOW");
    DO_str           = Parrot_str_new_constant(interp, "$!do");
    NAME_str         = Parrot_str_new_constant(interp, "name");
    SELF_str         = Parrot_str_new_constant(interp, "self");
    BLOCK_str        = Parrot_str_new_constant(interp, "Block");
    CAPTURE_str      = Parrot_str_new_constant(interp, "Capture");
    STORAGE_str      = Parrot_str_new_constant(interp, "$!storage");
    REST_str         = Parrot_str_new_constant(interp, "$!rest");
    LIST_str         = Parrot_str_new_constant(interp, "$!list");
    HASH_str         = Parrot_str_new_constant(interp, "$!hash");
    FLATTENS_str     = Parrot_str_new_constant(interp, "$!flattens");
    NEXTITER_str     = Parrot_str_new_constant(interp, "$!nextiter");
    HASH_SIGIL_str   = Parrot_str_new_constant(interp, "%");
    ARRAY_SIGIL_str  = Parrot_str_new_constant(interp, "@");
    BANG_TWIGIL_str  = Parrot_str_new_constant(interp, "!");
    SCALAR_SIGIL_str = Parrot_str_new_constant(interp, "$");
    NAMED_str        = Parrot_str_new_constant(interp, "named");
    INSTANTIATE_GENERIC_str = Parrot_str_new_constant(interp, "instantiate_generic");
    
    smo_id  = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
    p6l_id  = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "Perl6LexPad", 0));
    qrpa_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "QRPA", 0));
}
Ejemplo n.º 2
0
/* Initializes the P6opaque representation. */
REPROps * P6opaque_initialize(PARROT_INTERP) {
    /* Allocate and populate the representation function table. */
    this_repr = mem_allocate_zeroed_typed(REPROps);
    this_repr->type_object_for = type_object_for;
    this_repr->allocate = allocate;
    this_repr->initialize = initialize;
    this_repr->copy_to = copy_to;
    this_repr->attr_funcs = mem_allocate_typed(REPROps_Attribute);
    this_repr->attr_funcs->get_attribute_boxed = get_attribute_boxed;
    this_repr->attr_funcs->get_attribute_ref = get_attribute_ref;
    this_repr->attr_funcs->bind_attribute_boxed = bind_attribute_boxed;
    this_repr->attr_funcs->bind_attribute_ref = bind_attribute_ref;
    this_repr->attr_funcs->is_attribute_initialized = is_attribute_initialized;
    this_repr->attr_funcs->hint_for = hint_for;
    this_repr->box_funcs = mem_allocate_typed(REPROps_Boxing);
    this_repr->box_funcs->set_int = set_int;
    this_repr->box_funcs->get_int = get_int;
    this_repr->box_funcs->set_num = set_num;
    this_repr->box_funcs->get_num = get_num;
    this_repr->box_funcs->set_str = set_str;
    this_repr->box_funcs->get_str = get_str;
    this_repr->box_funcs->get_boxed_ref = get_boxed_ref;
    this_repr->gc_mark = gc_mark;
    this_repr->gc_free = gc_free;
    this_repr->gc_mark_repr_data = gc_mark_repr_data;
    this_repr->gc_free_repr_data = gc_free_repr_data;
    this_repr->get_storage_spec = get_storage_spec;
    this_repr->change_type = change_type;
    this_repr->serialize = serialize;
    this_repr->deserialize = deserialize;
    this_repr->serialize_repr_data = serialize_repr_data;
    this_repr->deserialize_repr_data = deserialize_repr_data;
    smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
    return this_repr;
}
Ejemplo n.º 3
0
Archivo: oo.c Proyecto: ashgti/parrot
PARROT_EXPORT
PARROT_CAN_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
PMC *
Parrot_oo_get_class(PARROT_INTERP, ARGIN(PMC *key))
{
    ASSERT_ARGS(Parrot_oo_get_class)
    PMC *classobj = PMCNULL;

    if (PMC_IS_NULL(key))
        return PMCNULL;

    if (PObj_is_class_TEST(key))
        classobj = key;
    else {
        /* Fast select of behavior based on type of the lookup key */
        switch (key->vtable->base_type) {
          case enum_class_NameSpace:
            classobj = VTABLE_get_class(interp, key);
            break;
          case enum_class_String:
          case enum_class_Key:
          case enum_class_ResizableStringArray:
            {
                PMC * const hll_ns = VTABLE_get_pmc_keyed_int(interp,
                                        interp->HLL_namespace,
                                        Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp)));
                PMC * const ns     = Parrot_ns_get_namespace_keyed(interp,
                                        hll_ns, key);

                if (!PMC_IS_NULL(ns))
                    classobj = VTABLE_get_class(interp, ns);
            }
          default:
            break;
        }
    }

    /* If the PMCProxy doesn't exist yet for the given key, we look up the
       type ID here and create a new one */
    if (PMC_IS_NULL(classobj)) {
        INTVAL type;
        const INTVAL base_type = key->vtable->base_type;

        /* This is a hack! All PMCs should be able to be handled through
           a single codepath, and all of them should be able to avoid
           stringification because it's so imprecise. */
        if (base_type == enum_class_Key
         || base_type == enum_class_ResizableStringArray
         || base_type == enum_class_String)
            type = Parrot_pmc_get_type(interp, key);
        else
            type = Parrot_pmc_get_type_str(interp, VTABLE_get_string(interp, key));

        classobj = get_pmc_proxy(interp, type);
    }

    return classobj;
}
Ejemplo n.º 4
0
PARROT_EXPORT
Parrot_Int
Parrot_PMC_typenum(PARROT_INTERP, ARGIN_NULLOK(const char *_class))
{
    ASSERT_ARGS(Parrot_PMC_typenum)
    Parrot_Int retval = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, _class, 0));
    return retval;
}
Ejemplo n.º 5
0
/* Gets the list of possible candidates to dispatch too. */
static PMC *get_dispatchees(PARROT_INTERP, PMC *dispatcher) {
    if (!smo_id)
        smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
    if (dispatcher->vtable->base_type == enum_class_Sub && PARROT_SUB(dispatcher)->multi_signature->vtable->base_type == smo_id) {
        NQP_Routine *r = (NQP_Routine *)PMC_data(PARROT_SUB(dispatcher)->multi_signature);
        return r->dispatchees;
    }
    else {
        Parrot_ex_throw_from_c_args(interp, 0, 1,
            "Could not find multi-dispatch list");
    }
}
Ejemplo n.º 6
0
/*

=item C<static void add_to_cache(PARROT_INTERP, NQP_md_cache *cache, PMC *capture, INTVAL num_args)>

Adds an entry to the multi-dispatch cache.

=cut

*/
void add_to_cache(PARROT_INTERP, NQP_md_cache *cache, PMC *capture, INTVAL num_args, PMC *result) {
    INTVAL arg_tup[MD_CACHE_MAX_ARITY];
    INTVAL i, entries, ins_type;
    struct Pcc_cell * pc_positionals;
    
    /* Make sure 6model type ID is set. */
    if (!smo_id)
        smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
    
    /* If it's zero arity, just stick it in that slot. */
    if (num_args == 0) {
        cache->zero_arity = result;
        return;
    }
    
    /* If the cache is saturated, don't do anything (we could instead do a random
     * replacement). */
    entries = cache->arity_caches[num_args - 1].num_entries;
    if (entries == MD_CACHE_MAX_ENTRIES)
        return;
    
    /* Create arg tuple. */
    if (capture->vtable->base_type == enum_class_CallContext)
        GETATTR_CallContext_positionals(interp, capture, pc_positionals);
    else
        return;
    for (i = 0; i < num_args; i++) {
        if (pc_positionals[i].type == BIND_VAL_OBJ) {
            PMC *arg = pc_positionals[i].u.p;
            if (arg->vtable->base_type != smo_id)
                return;
            arg_tup[i] = STABLE(arg)->type_cache_id | (IS_CONCRETE(arg) ? 1 : 0);
        }
        else {
            arg_tup[i] = (pc_positionals[i].type << 1) | 1;
        }
    }

    /* If there's no entries yet, need to do some allocation. */
    if (entries == 0) {
        cache->arity_caches[num_args - 1].type_ids = mem_sys_allocate(num_args * sizeof(INTVAL) * MD_CACHE_MAX_ENTRIES);
        cache->arity_caches[num_args - 1].results  = mem_sys_allocate(sizeof(PMC *) * MD_CACHE_MAX_ENTRIES);
    }

    /* Add entry. */
    ins_type = entries * num_args;
    for (i = 0; i < num_args; i++)
        cache->arity_caches[num_args - 1].type_ids[ins_type + i] = arg_tup[i];
    cache->arity_caches[num_args - 1].results[entries] = result;
    cache->arity_caches[num_args - 1].num_entries = entries + 1;
}
Ejemplo n.º 7
0
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC *
blizkost_wrap_sv(BLIZKOST_NEXUS, SV *sv) {
    dBNPERL; dBNINTERP;
    PMC *wrapper = Parrot_pmc_new_noinit(interp, Parrot_pmc_get_type_str(interp,
                Parrot_str_new_constant(interp, "P5Scalar")));

    PObj_custom_mark_SET(wrapper);
    PObj_custom_destroy_SET(wrapper);

    SETATTR_P5Scalar_nexus(interp, wrapper, nexus);
    SETATTR_P5Scalar_sv(interp, wrapper, SvREFCNT_inc(sv));
    return wrapper;
}
Ejemplo n.º 8
0
/* Gets (creating if needed) a multi-dispatch cache. */
static NQP_md_cache *get_dispatch_cache(PARROT_INTERP, PMC *dispatcher) {
    PMC *cache_ptr;
    if (!smo_id)
        smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
    if (dispatcher->vtable->base_type == enum_class_Sub && PARROT_SUB(dispatcher)->multi_signature->vtable->base_type == smo_id) {
        NQP_Routine *r = (NQP_Routine *)PMC_data(PARROT_SUB(dispatcher)->multi_signature);
        if (PMC_IS_NULL(r->dispatch_cache)) {
            NQP_md_cache *c = mem_sys_allocate_zeroed(sizeof(NQP_md_cache));
            cache_ptr = Parrot_pmc_new(interp, enum_class_Pointer);
            VTABLE_set_pointer(interp, cache_ptr, c);
            r->dispatch_cache = cache_ptr;
            PARROT_GC_WRITE_BARRIER(interp, PARROT_SUB(dispatcher)->multi_signature);
        }
        else {
            cache_ptr = r->dispatch_cache;
        }
    }
    else {
        Parrot_ex_throw_from_c_args(interp, 0, 1,
            "Could not find multi-dispatch list");
    }
    return (NQP_md_cache *)VTABLE_get_pointer(interp, cache_ptr);
}
Ejemplo n.º 9
0
/* Performs a multiple dispatch using the candidates held in the passed
 * DispatcherSub and using the arguments in the passed capture. */
PMC *nqp_multi_dispatch(PARROT_INTERP, PMC *dispatcher, PMC *capture) {
    /* Get list and number of dispatchees. */
    PMC *dispatchees = PARROT_DISPATCHERSUB(dispatcher)->dispatchees;
    const INTVAL num_candidates = VTABLE_elements(interp, dispatchees);

    /* Count arguments. */
    const INTVAL num_args = VTABLE_elements(interp, capture);

    /* Initialize dispatcher state. */
    INTVAL type_mismatch;
    INTVAL possibles_count = 0;
    candidate_info **possibles = mem_allocate_n_typed(num_candidates, candidate_info *);
    INTVAL type_check_count;

    /* Get sorted candidate list.
     * XXX We'll cache this in the future. */
    candidate_info** candidates    = sort_candidates(interp, dispatchees);
    candidate_info** cur_candidate = candidates;

    /* Ensure we know what is a 6model object and what is not. */
    if (!smo_id)
        smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));

    /* Iterate over the candidates and collect best ones; terminate
     * when we see two nulls (may break out earlier). */
    while (1) {
        INTVAL i;

        if (*cur_candidate == NULL) {
            /* If we have some possible candidate(s), we're done in this loop. */
            if (possibles_count)
                break;

            /* Otherwise, we keep looping and looking, unless we really hit the end. */
            if (cur_candidate[1]) {
                cur_candidate++;
                continue;
            }
            else {
                break;
            }
        }

        /* Check if it's admissable by arity. */
        if (num_args < (*cur_candidate)->min_arity || num_args > (*cur_candidate)->max_arity) {
            cur_candidate++;
            continue;
        }

        /* Check if it's admissable by type. */
        type_check_count = (*cur_candidate)->num_types > num_args
                           ? num_args
                           : (*cur_candidate)->num_types;
        type_mismatch = 0;

        for (i = 0; i < type_check_count; i++) {
            PMC * const param = VTABLE_get_pmc_keyed_int(interp, capture, i);
            PMC * const param_type = param->vtable->base_type == smo_id ?
                                     STABLE(param)->WHAT : PMCNULL;
            PMC * const type_obj = (*cur_candidate)->types[i];
            INTVAL const definedness = (*cur_candidate)->definednesses[i];
            if (param_type != type_obj && !is_narrower_type(interp, param_type, type_obj)) {
                type_mismatch = 1;
                break;
            }
            if (definedness) {
                /* Have a constraint on the definedness. */
                INTVAL defined = param->vtable->base_type == smo_id ?
                                 IS_CONCRETE(param) :
                                 VTABLE_defined(interp, param);
                if ((!defined && definedness == DEFINED_ONLY) || (defined && definedness == UNDEFINED_ONLY)) {
                    type_mismatch = 1;
                    break;
                }
            }
        }

        if (type_mismatch) {
            cur_candidate++;
            continue;
        }

        /* If we get here, it's an admissable candidate; add to list. */
        possibles[possibles_count] = *cur_candidate;
        possibles_count++;
        cur_candidate++;
    }

    /* Cache the result if there's a single chosen one. */
    if (possibles_count == 1) {
        /* XXX TODO: Cache entry. */
    }

    /* Need a unique candidate. */
    if (possibles_count == 1) {
        PMC *result = possibles[0]->sub;
        mem_sys_free(possibles);
        return result;
    }
    else if (possibles_count == 0) {
        /* Get signatures of all possible candidates. We dump them in the
         * order in which we search for them. */
        STRING *signatures = Parrot_str_new(interp, "", 0);
        cur_candidate = candidates;
        while (1) {
            if (!cur_candidate[0] && !cur_candidate[1])
                break;
            /* XXX TODO: add sig dumping.
            if (cur_candidate[0])
                signatures = dump_signature(interp, signatures, (*cur_candidate)->sub); */
            cur_candidate++;
        }

        mem_sys_free(possibles);
        Parrot_ex_throw_from_c_args(interp, NULL, 1,
                                    "No applicable candidates found to dispatch to for '%Ss'. Available candidates are:\n%Ss",
                                    VTABLE_get_string(interp, candidates[0]->sub),
                                    signatures);
    }
    else {
        /* Get signatures of ambiguous candidates. */
        STRING *signatures = Parrot_str_new(interp, "", 0);
        INTVAL i;
        /* XXX TODO: sig dumping
        for (i = 0; i < possibles_count; i++)
            signatures = dump_signature(interp, signatures, possibles[i]->sub); */
        mem_sys_free(possibles);
        Parrot_ex_throw_from_c_args(interp, NULL, 1,
                                    "Ambiguous dispatch to multi '%Ss'. Ambiguous candidates had signatures:\n%Ss",
                                    VTABLE_get_string(interp, candidates[0]->sub), signatures);
    }
}