Cómo imprimir un objeto, escriba en NQP

Tinmarino:

Cómo imprimir un objeto en NQP? (Para propósitos de depuración)

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 .gistmétodo, los códigos de llamadas nqp::encodeque finalmente se espera una cadena.

rafe:

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 Strmé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 Strmé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 Strmé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 .sayen 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 $stra 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.cen 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 Strmétodo

Tendrá que personalizar el Strmé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 $!baratributo 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 sayrutina 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.

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=406231&siteId=1
Recomendado
Clasificación