Cómo imprimir un objeto en NQP? (Para propósitos de depuración)
Es fácil de Raku:
- decir que está llamando lo esencial en su bucle corto código
- dd El diminuto Volquete de datos como se muestra en este puesto
class Toto { has $.member = 42; }
class Titi { has $.member = 41; has $.toto = Toto.new }
my $ti = Titi.new;
say $ti;
# Titi.new(member => 41, toto => Toto.new(member => 42))
dd $ti;
# Titi $ti = Titi.new(member => 41, toto => Toto.new(member => 42))
- Parece más complicado en NQP
class Toto { has $!member; sub create() {$!member := 42}};
class Titi { has $!member; has $!toto; sub create() {$!member := 41; $!toto := Toto.new; $!toto.create; }}
my $ti := Titi.new;
say($ti);
Cannot stringify this object of type P6opaque (Titi)
Por supuesto, ningún .gist
método, los códigos de llamadas nqp::encode
que finalmente se espera una cadena.
Reducir el problema a una ERM :
class foo {}
say(foo.new); # Cannot stringify ...
La simplificación de la solución:
class foo { method Str () { 'foo' } }
say(foo.new); # foo
En resumen, añadir un Str
método.
Esto suena simple, pero hay un montón de detrás de las escenas cosas para considerar / explicar.
NQP vs raku
La solución anterior es los mismos usos técnica raku; cuando se espera un valor por una rutina / operación para ser una cadena, pero no lo es, el comportamiento lingüístico es tratar de coaccionar a una cadena. En concreto, a ver si hay un Str
método que se puede llamar en el valor, y si es así, lo llaman.
En este caso NQP deNQPMu
, que es la forma más barebones que raku deMu
, no proporciona ningún defecto Str
método. Por lo que una solución es añadir manualmente una.
De manera más general, NQP es un lenguaje bastante hostil a menos que sepa raku bastante bien y ha pasado a través de un curso sobre Rakudo y NQP internos .
Y una vez que esté al día en el material en ese curso, recomiendo se tiene en cuenta los canales de IRC # raku-dev y / o #moarvm como su primer puerto de escala en lugar de SO (a menos que su objetivo es específicamente para aumentar la cobertura de SO de NQP / moarvm).
Depuración del código de compilador
Como habrá visto, el código NQP que vincula las llamadas .say
en un gestor de archivo.
Que luego se llama a este método .
El cuerpo de ese método es $str ~ "\n"
. Ese código intentará coaccionar $str
a una cadena (al igual que lo haría en raku). Eso es lo que va a estar generando el error "No se puede stringify".
Una búsqueda de "No se puede stringify" en el NQP Repo solo coincidan con algo de código Java. Y apuesto a que no se está ejecutando Rakudo en la JVM. Eso significa que el mensaje de error debe venir de MoarVM.
La misma búsqueda en el repositorio MoarVM produce esta línea en coerce.c
en MoarVM .
Mirando hacia atrás en la rutina que contienen esa línea que vemos este bit :
/* Check if there is a Str method. */
MVMROOT(tc, obj, {
strmeth = MVM_6model_find_method_cache_only(tc, obj,
tc->instance->str_consts.Str);
});
Esto muestra el back-end, escrito en C, buscando e invocando un "método" llamada Str
. (Se depender de una API interna (6model) que las tres capas del compilador (raku, NQP y backends) se adhieren a.)
Personalización del Str
método
Tendrá que personalizar el Str
método según el caso. Por ejemplo, para imprimir el nombre de la clase si se trata de un objeto de tipo, y el valor de su $!bar
atributo de otro modo:
class foo {
has $!bar;
method Str () { self ?? nqp::coerce_is($!bar) !! self.HOW.name(self) }
}
say(foo.new(bar=>42)); # 42
A pesar del nombre del método, la NQP say
rutina es que no esperaba un raku Str
, sino más bien una cadena nativa NQP (que termina siendo una cadena nativa MoarVM en el backend MoarVM). De ahí la necesidad de nqp::coerce_is
(que he encontrado navegando por el doctor ops NQP ).
self.HOW.name(self)
es otro ejemplo de la forma en NQP simplemente no tiene las sutilezas que tiene raku. Usted podría escribir el mismo código en raku pero la forma idiomática escribirlo en raku es self.^name
.