# New Ticket Created by Leopold Toetsch
# Please include the string: [perl #20315]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=20315 >
Attached is a first try towards eval.
- interpreter has a new data member Parrot_compreg_hash
- parrot registers the PASM1 type i.e. what PDB_eval can parse
- the new B<compile> opcode (ab)uses nci to build a function for calling
PDB_eval
- nci is extended (jit/i386 only), to understand an 'I' param as interpreter
- the string is evaled immediately, we don't have multiple byte code
segments yet
No registers, which nci uses, are preserved, no error checking and so
on, but works ;-)
Some questions arise here:
- Should the B<compreg> opcode also have a form with a label to build
PASM compilers, ook?
- is using the NCI interface ok for evals purpose?
- how should a byte code segment (PMC) look like?
Comment welcome
leo
-- attachment 1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/48556/37739/ade5a5/eval.patch
--- parrot/classes/csub.pmc Fri Jan 10 18:05:02 2003
+++ parrot-leo/classes/csub.pmc Tue Jan 14 19:06:24 2003
@@ -49,7 +49,7 @@
return SELF->cache.struct_val != NULL;
}
- void * invoke (void * next) {
+ void* invoke (void * next) {
Parrot_csub_t func = (Parrot_csub_t)SELF->cache.struct_val;
func(INTERP, SELF);
return next;
--- parrot/core.ops Tue Jan 14 09:09:55 2003
+++ parrot-leo/core.ops Tue Jan 14 19:25:19 2003
@@ -4485,6 +4485,10 @@
Call the subroutine in P0, as described in PDD03.
+=item B<compile>(out PMC, in STR, in STR)
+
+Compile source code $2 of a registered source type $3 into PMC $1.
+
=cut
inline op loadext(in STR, in STR) {
@@ -4547,6 +4551,19 @@
goto ADDRESS(dest);
}
+
+inline op compile(OUT PMC, in STR, in STR) {
+ opcode_t *dest;
+ PMC *key = key_new_string(interpreter, $3);
+ PMC *func = interpreter->Parrot_compreg_hash->vtable->get_pmc_keyed(
+ interpreter, interpreter->Parrot_compreg_hash, key);
+ /* XXX undef */
+ interpreter->ctx.string_reg.registers[5] = $2; /* XXX */
+ dest = (opcode_t *)func->vtable->invoke(interpreter, func, expr NEXT());
+ /* XXX retval */
+ goto ADDRESS(dest);
+}
+
=item B<find_method>(out PMC, in PMC, in STR)
--- parrot/dod.c Tue Jan 14 09:09:55 2003
+++ parrot-leo/dod.c Tue Jan 14 18:51:15 2003
@@ -104,6 +104,8 @@
/* mark it as used */
pobject_lives(interpreter, (PObj *)current);
+ if (interpreter->Parrot_compreg_hash)
+ pobject_lives(interpreter, (PObj *)interpreter->Parrot_compreg_hash);
/* Now, go run through the PMC registers and mark them as live */
/* First mark the current set. */
for (i = 0; i < NUM_REGISTERS; i++) {
--- parrot/include/parrot/interpreter.h Sat Jan 4 12:35:22 2003
+++ parrot-leo/include/parrot/interpreter.h Tue Jan 14 18:13:08 2003
@@ -169,6 +169,7 @@
INTVAL world_inited; /* Parrot_init is done */
PMC *mark_ptr; /* last PMC marked used in DOD runs */
PMC *Parrot_base_classname_hash; /* hash containing name->base_type */
+ PMC *Parrot_compreg_hash; /* hash containing assembler/compilers */
} Interp;
#define PCONST(i) PF_CONST(interpreter->code, (i))
@@ -189,6 +190,7 @@
VAR_SCOPE opcode_t *(*run_native)(struct Parrot_Interp * interpreter,
opcode_t * cur_opcode,
opcode_t * start_code);
+void Parrot_compreg(Parrot_Interp interpreter, STRING *type, PMC *func);
#endif /* Parrot core */
--- parrot/interpreter.c Sat Jan 11 09:39:08 2003
+++ parrot-leo/interpreter.c Tue Jan 14 19:21:00 2003
@@ -21,11 +21,13 @@
#ifdef HAVE_COMPUTED_GOTO
# include "parrot/oplib/core_ops_cg.h"
#endif
+#include "parrot/method_util.h"
#define ATEXIT_DESTROY
extern op_lib_t *PARROT_CORE_PREDEREF_OPLIB_INIT(void);
+static void setup_default_compreg(Parrot_Interp interpreter);
/*=for api interpreter runops_generic
* TODO: Not really part of the API, but here's the docs.
@@ -512,6 +514,10 @@
SET_NULL_P(interpreter->prederef_code, void **);
SET_NULL(interpreter->jit_info);
+ SET_NULL_P(interpreter->Parrot_compreg_hash, PMC *);
+ /* register assembler/compilers */
+ setup_default_compreg(interpreter);
+
/* Done. Return and be done with it */
/* Okay, we've finished doing anything that might trigger GC.
@@ -686,6 +692,42 @@
}
return ret;
}
+
+/*=for api interpreter Parrot_compreg
+ * register a parser/compiler function
+ */
+
+void Parrot_compreg(Parrot_Interp interpreter, STRING *type, PMC *func)
+{
+ PMC* key, *hash;
+ if (!interpreter->Parrot_compreg_hash) {
+ hash = interpreter->Parrot_compreg_hash =
+ pmc_new_noinit(interpreter, enum_class_PerlHash);
+ hash->vtable->init(interpreter, hash);
+ }
+ key = key_new_string(interpreter, type);
+ hash->vtable->set_pmc_keyed(interpreter, hash, key, func, NULL);
+}
+
+void PDB_eval_wrapper(Parrot_Interp interpreter, STRING *code);
+void PDB_eval_wrapper(Parrot_Interp interpreter, STRING *code)
+{
+ char *s = string_to_cstring(interpreter, code);
+ PDB_eval(interpreter, s);
+ free(s);
+}
+
+static void setup_default_compreg(Parrot_Interp interpreter)
+{
+ STRING *pasm1 = string_make(interpreter, "PASM1", 5, NULL,0,NULL);
+ PMC * func;
+ Parrot_csub_t p = (Parrot_csub_t) F2DPTR(PDB_eval);
+ func = Parrot_new_nci(interpreter, p,
+ string_make(interpreter, "pIt", 3, NULL,0,NULL));
+ Parrot_compreg(interpreter, pasm1, func);
+}
+
+
/*
* Local variables:
* c-indentation-style: bsd
--- parrot/jit/i386/jit_emit.h Tue Jan 14 10:34:02 2003
+++ parrot-leo/jit/i386/jit_emit.h Tue Jan 14 21:10:53 2003
@@ -2137,6 +2137,9 @@
emitm_addb_i_r(pc, 8, emit_ESP);
emitm_pushl_r(pc, emit_EAX);
break;
+ case 'I':
+ emitm_pushl_i(pc, interpreter);
+ break;
default:
internal_exception(1,
"Parrot_jit_build_call_func: unimp argument\n");
--- /dev/null Tue Oct 10 22:47:19 2000
+++ parrot-leo/eval.pasm Tue Jan 14 19:33:57 2003
@@ -0,0 +1,4 @@
+ compile P1, "set_s_sc S1, '42\n'", "PASM1"
+ compile P1, "print_s S1", "PASM1"
+ print "\n"
+ end