BEGIN_OPS_PREAMBLE
opcode_t *
Parrot_pir_op_lib_wrapper_func(opcode_t *cur_opcode, PARROT_INTERP)
{
// TODO: Set dest to the address of the next instruction, after all arguments.
// need to parse the number of args from the op signature
opcode_t * dest = cur_opcode + 3;
INTVAL opnum = (INTVAL)(*cur_opcode);
char * const opname = interp->op_info_table[opnum]->name;
STRING * name = string_make(interp, opname, 8, "ascii",
PObj_constant_FLAG|PObj_external_FLAG);
PMC * const root_ns = interp->root_namespace;
PMC * const ns = Parrot_get_namespace_keyed(interp, root_ns, CONST_STRING(interp, "pir_op_lib"));
PMC * sub = VTABLE_get_pmc_keyed_str(interp, ns, name);
// TODO: Need to convert the op signature into a PCC signature here
PMC * call_sig = Parrot_pcc_build_sig_object_from_op(interp, PMCNULL, signature,
cur_opcode);
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), call_sig);
interp->current_cont = NEED_CONTINUATION;
dest = VTABLE_invoke(interp, sub, dest);
goto ADDRESS(dest);
}
END_OPS_PREAMBLE
op register_op_sub(IN STR, IN STR, IN PMC) {
PMC * const root_ns = interp->root_namespace;
PMC * const sub = $3;
PMC * const key = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
STRING * const opname = $1;
STRING * const sig = $2;
PMC * const ns = Parrot_get_namespace_keyed(interp, root_ns, CONST_STRING(interp, "pir_op_lib"));
INTVAL argcount = 3; // TODO: Count number of args in signature
STRING * const separator = CONST_STRING(interp, "_");
STRING * longname = Parrot_str_append(interp, opname, separator);
longname = Parrot_str_append(interp, longname, sig);
VTABLE_set_string_keyed_int(interp, key, 0, );
VTABLE_set_pmc_keyed_str(interp, ns, $2, sub);
op_info_t * new_op = (op_info_t *)malloc(sizeof(op_info_t));
new_op->name = Parrot_str_to_cstring(interp, opname);
new_op->full_name = Parrot_str_to_cstring(interp, longname);
new_op->jump = 0;
new_op->opcount = argcount + 1;
// TODO: Initialize ->type based on what's in signature
new_op->type = (arg_type_t *)malloc(sizeof(arg_type_t) * PARROT_MAX_ARGS);
// TODO: Initialize based on the signature
new_op->dirs = (arg_dir_t *)malloc(sizeof(arg_dir_t) * PARROT_MAX_ARGS);
// TODO: what is this?
new_op->labels = (char *)malloc(sizeof(char) * PARROT_MAX_ARGS);
// TODO: Insert the new op into the optable.
}This code, intended to become a dynop library one day, introduces a single new op: register_op_sub. register_op_sub takes three arguments: the string name of the new op, the string signature of the new op, and the Sub PMC for the new op. An entry is prepared for the interpreter's op_lib table (I haven't found a good way to insert that record yet), and the sub is stored in the "pir_op_lib" namespace. The body of the new op is the function Parrot_pir_op_lib_wrapper. This function body looks up the name of the current op in the op_lib table, then looks up the Sub PMC in the namespace, and will attempt to invoke that sub.
I haven't worked out all the mechanics of everything, obviously. But once a few more questions get answered and a modest amount of code gets written, this could turn into a very useful and very cool extension library for Parrot.

No comments:
Post a Comment
Note: Only a member of this blog may post a comment.