Parrot - Ejemplos de programación



Parrot programación es similar al lenguaje ensamblador programación y tienes la oportunidad de trabajar en un nivel inferior. Aquí está la lista de ejemplos de programación para que tenga en cuenta los diversos aspectos de programación Loro.

Clásico Hola mundo!

Cree un archivo llamado hello.pir que contiene el siguiente código:

.sub _main
   print "Hello world!\n"
   end
.end

A continuación, ejecutar tecleando:

parrot hello.pir

Como era de esperar, se mostrará el texto 'Hello world!' en la consola, seguido de un carácter de nueva línea (debido a la \n).

En el ejemplo anterior, '.sub _main' de los estados que las instrucciones que se detallan a continuación constituyen una subrutina llamada '_main', hasta que un '.end' han encontrado. La segunda línea contiene la instrucción de impresión. En este caso, nos están pidiendo la variante de la instrucción que acepta una constante de cadena. El ensamblador se encarga de decidir qué variante de las instrucciones de uso para nosotros. La tercera línea, el 'end' instrucciones, lo que provoca que el intérprete para terminar.

Utilizando Registros

Podemos modificar hola.pir a primera tienda la cadena Hello world!\n en un registro y, a continuación, utilice el registro con la instrucción de impresión.

.sub _main
   set S1, "Hello world!\n"
   print S1
   end
.end

Aquí hemos dicho exactamente que registrarse para usar. Sin embargo, por S1 a $S1 podemos delegar la elección de que registrarse para usar de Parrot. También es posible utilizar un = notación en lugar de escribir las instrucciones.

.sub _main
   $S0 = "Hello world!\n"
   print $S0
   end
.end

PIR para que sea aún más legible, llamado registros pueden ser utilizados. Estos son más tarde asignado a real registros numerados.

.sub _main
   .local string hello
   hello = "Hello world!\n"
   print hello
   end
.end

El '.local' directiva indica que el registro sólo es necesario dentro de la misma unidad de compilación (es decir, entre .sub y .final). Después de un '.local' es un tipo. Esto puede ser int (para I registros), flotación (para N registros), cadena (para S registros), pmc (para P registros) o el nombre de un tipo.

Resumen plazas

Este ejemplo presenta algunas más instrucciones y sintaxis PIR. Las líneas que comienzan con # son comentarios.

.sub _main
   # State the number of squares to sum.
   .local int maxnum
   maxnum = 10

   # Some named registers we'll use. 
   # Note how we can declare many
   # registers of the same type on one line.
   .local int i, total, temp
   total = 0

   # Loop to do the sum.
   i = 1
   
loop:
   temp = i * i
   total += temp
   inc i
   if i <= maxnum goto loop

   # Output result.
   print "The sum of the first "
   print maxnum
   print " squares is "
   print total
   print ".\n"
   end
.end

PIR proporciona un poco de azúcar sintáctica que lo hacen ver más alto nivel de la asamblea. Por ejemplo:

temp = i * i

Es simplemente otra forma de escribir el más asamblea de ish:

mul temp, i, i

Y:

if i <= maxnum goto loop

Es el mismo:

le i, maxnum, loop

Y:

total += temp

Es el mismo:

add total, temp

Como regla general, cada vez que un loro instrucción modifica el contenido de un registro, que será el primer registro cuando por escrito las instrucciones en conjunto.

Como es habitual en lenguajes ensambladores, los ciclos y las selecciones se implementan en términos de bifurcaciones condicionales las declaraciones y etiquetas, como se ha indicado anteriormente. Aprendizaje Conjunto es uno de los lugares donde uso de goto no es una mala forma!

Números de Fibonacci

La serie de Fibonacci es definido como sigue: dos números, 1 y 1. A continuación, varias veces sumar los últimos dos números de la serie para hacer el siguiente: 1, 1, 2, 3, 5, 8, 13, y así sucesivamente. La serie de Fibonacci el fib(n) es el n'th número de la serie. He aquí una simple Parrot programa ensamblador que considera los 20 primeros números de Fibonacci:

# Some simple code to print some Fibonacci numbers

        print   "The first 20 fibonacci numbers are:\n"
        set     I1, 0
        set     I2, 20
        set     I3, 1
        set     I4, 1
        
REDO:   eq      I1, I2, DONE, NEXT

NEXT:   set     I5, I4
        add     I4, I3, I4
        set     I3, I5
        print   I3
        print   "\n"
        inc     I1
        branch  REDO
DONE:   end

Este es el código equivalente en Perl:

print "The first 20 fibonacci numbers are:\n";

my $i = 0;
my $target = 20;
my $a = 1;
my $b = 1;

until ($i == $target) {
   my $num = $b;
   $b += $a;
   $a = $num;
   print $a,"\n";
   $i++;
}

NOTA: Es un buen punto de interés, uno de los más cortos y, sin duda, la más hermosa manera de imprimir una serie de Fibonacci en Perl es perl -le '$b=1; print $a+=$b, mientras que print $b+=$a'.

Cálculo factorial recursivo

En este ejemplo, definimos una función factorial y llamar de forma recursiva para calcular el factorial.

.sub _fact
   # Get input parameter.
   .param int n

   # return (n > 1 ? n * _fact(n - 1) : 1)
   .local int result

   if n > 1 goto recurse
   result = 1
   goto return

recurse:
   $I0 = n - 1
   result = _fact($I0)
   result *= n

return:
   .return (result)
.end


.sub _main :main
   .local int f, i

   # We'll do factorial 0 to 10.
   i = 0
   
loop:
   f = _fact(i)

   print "Factorial of "
   print i
   print " is "
   print f
   print ".\n"

   inc i
   if i <= 10 goto loop

   # That's it.
   end
.end

Echemos un vistazo a la _fact sub primero. Un punto en el que se evoca con respecto a las anteriores es por qué los nombres de subrutinas, todos comienzan con un carácter de subrayado. Esto se hace simplemente como una manera de mostrar que la etiqueta es global y no particular ámbito de una subrutina. Esto es importante ya que las etiquetas se hace visible a otras subrutinas.

La primera línea, .param int n, especifica que esta subrutina toma un parámetro de entero y que nos gustaría hacer referencia al registro que fue aprobada por el nombre n para el resto de la sub.

Gran parte de lo que sigue se ha visto en ejemplos anteriores, aparte de la línea siguiente:

result = _fact($I0)

Esta única línea de PIR en realidad representa unas cuantas líneas de modo PASM. En primer lugar, el valor del registro $I0 se mueve en el registro correspondiente para que sea recibido como un parámetro de entero por la _fact función. Otros que están relacionados con registros, a continuación, configurar, seguido por _fact que se invoca. A continuación, una vez _fact devuelve el valor devuelto por _fact se coloca en el registro le da el nombre.

Justo antes de que el .fin de la _fact sub, .directiva de retorno se utiliza para garantizar el valor almacenado en el registro, denominado resultado se coloca en el registro correcto para que se vea como un valor de retorno en el código que llama al sub.

La llamada a _fact en principal funciona de la misma forma como el recursivo llamar a _fact dentro de la _fact sub sí mismo. El único bit restantes de la nueva sintaxis es :principal, escrito después de .sub _main. De forma predeterminada, PIR se supone que la ejecución comienza con la primera sub en el archivo. Este comportamiento se puede modificar mediante el marcado de la subcomisión para iniciar con :principales.

Compilación de PBC

Para compilar PIR a bytecode, utilice el distintivo -o y especificar un archivo de salida con la extensión .pbc.

Parrot -o factorial.cpp factorial.pir

PIR vs. PASM

PIR puede transformarse en PASM ejecutando:

parrot -o hello.pasm hello.pir

El modo PASM para el ejemplo final tiene este aspecto:

_main:
   set S30, "Hello world!\n"
   print S30
end

PASM no maneja asignación de registros o proporcionar apoyo para registros. También no tiene el .sub y .final las directivas, en lugar de una etiqueta en el inicio de las instrucciones.

Advertisements