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.