Parrot - Programmierbeispiele


Advertisements


Parrot Programmierung ist ähnlich wie Assembler-Programmierung und Ihnen eine Chance, auf einer niedrigeren Ebene zu arbeiten. Hier ist die Liste der Programmierbeispiele Sie Kenntnis von den verschiedenen Aspekten der Parrot Programmierung zu machen.

Klassische Hallo Welt!

Erstellen Sie eine Datei namens hello.pir, die den folgenden Code enthält:

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

Dann führen Sie es, indem Typisierung:

parrot hello.pir

Wie erwartet, wird dies den Text anzuzeigen 'Hallo Welt!' auf der Konsole, gefolgt von einer neuen Zeile (aufgrund der \ n).

In diesem Beispiel oben '.sub _main' besagt, dass die Anweisungen, die machen ein Unterprogramm mit dem Namen '_main' bis ein '.end' wird angetroffen. Die zweite Zeile enthält den Druckbefehl. In diesem Fall rufen wir die Variante des Befehls, der einen konstanten String annimmt. Der Assembler kümmert entscheiden, welche Variante der Anweisung, um für uns zu nutzen. Die dritte Zeile enthält die 'end' Befehl, der bewirkt, dass der Interpreter zu beenden.

verwendung Registern

Wir können hello.pir ändern, zu erst die Zeichenfolge speichern Hallo Welt! \ n in einem Register und verwenden Sie dann, dass mit dem Druckanweisung registrieren..

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

Hier wir haben genannt genau welche zu verwendende registrieren angegeben. Jedoch durch Ersetzen S1 mit $ S1 können wir die Wahl, welche Registrierung zur Nutzung zu Parrot delegieren. Es ist auch möglich, eine = Schreibweise anstelle des Schreibens des Satzes Anweisung verwenden.

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

Um PIR noch lesbar zu machen, können benannt Register verwendet werden. Diese werden später zu Echt nummerierten Register abgebildet.

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

Die ".local" Richtlinie gibt an dass der benannte Register wird nur brauchte innerhalb der aktuellen Zusammenstellung erforderlich (dh zwischen .sub und .end). folgende ".local" ist eine Art. Dies kann int (für I-Register), float (für N-Register), string (für S-Register), pmc (für P-Register) oder der Name einer PMC-Typ sein..

Summiereinrichtung Quadrate

Dieses Beispiel führt einige weitere Anweisungen und PIR-Syntax. Zeilen, start-die mit einem # sind Kommentare.

.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 bietet ein bisschen syntaktischer Zucker, die es mehr hohe ebene als Montage aussehen lässt. beispielsweise:

temp = i * i

Ist nur eine andere Art des Schreibens der weitere Montage-ish:

mul temp, i, i

Und:

if i <= maxnum goto loop

Ist die gleiche wie:

le i, maxnum, loop

Und:

total += temp

Ist die gleiche wie:

add total, temp

In der Regel, wenn ein Papagei Anweisungen ändert den Inhalt eines Registers, das wird das erste Register beim Schreiben der Unterricht in Montageform sein. .

Wie üblich in Assemblersprachen, Loops und Selektionen werden in Form von bedingten Verzweigungs Aussagen und Labels umgesetzt, wie oben gezeigt. Assembler-Programmierung ist ein Ort, an dem verwendung goto ist keine schlechte Form!

Fibonacci-Zahlen

Die Fibonacci-Reihe ist wie folgt definiert: Nehmen Sie zwei Zahlen, 1 und 1. Dann wiederholt addieren die letzten beiden Zahlen in der Reihe, um die nächste: 1, 1, 2, 3, 5, 8, 13, und so weiter. Die Fibonacci-Zahl fib (n) die n-te Nummer in der Reihe. Hier ist eine einfache Parrot Assembler-Programm, das die ersten 20 Fibonacci-Zahlen findet::

# 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

Dies ist der entsprechende Code in 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++;
}

Hinweis: als feiner Punkt von Interesse, eine der kürzesten und sicherlich schönsten Möglichkeiten der Drucken eines Fibonacci-Reihe in Perl wird perl -le '$ b = 1; drucke $ a + = $ b, während drucke $ b + = $ a '.

rekursiv Rechen Faktoriellen

In diesem Beispiel definieren wir eine Fakultätsfunktion und rekursiv anruf Es zu berechnen faktorielle.

.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

Lassen Sie uns schauen an das _fact Sub ersten. Ein Punkt, der gegenüber früheren beschönigt wurde ist warum die Namen der Unterprogramme, alle beginnen mit einem Unterstrich! Dies wird einfach als eine Möglichkeit zu zeigen, dass die Markierung global und nicht auf eine bestimmte Subroutine scoped geführt. Dies ist von Bedeutung, wenn das Etikett wird dann auf andere Unterprogramme sichtbar. .

Die erste Zeile, .param int n, gibt an, dass dieses Unterprogramm nimmt einen Integer-Parameter und wir möchten,zu verweisen dass auf das zu registrieren wurde es weitergegeben in durch Namen n für den Rest des sub ..

Vieles von dem, was folgt, in den vorherigen Beispielen gesehen hat, abgesehen von der Zeile Lesen::

result = _fact($I0)

Das Single Zeile von PIR eigentlich stellt ganz wenigen Zeilen von PASM . Zuerst wird der Wert ist registrieren zu $ I0 ist in das entsprechende Register verschoben um es als ein ganzzahliger Parameter durch _fact Funktion empfangen werden. Andere Aufruf verbundenen Register werden dann aufgestellt, gefolgt von _fact aufgerufen wird. Dann, wenn _fact kehrt der Wert kehrte von _fact ist stellt in das Register angesichts der Name Ergebnis ..

Rechts vor dem .end der _fact sub, ein .return Direktive wird benutzt, um den Wert in dem Register gehalten zu gewährleisten; benannt Ergebnis wird in das richtige register abgelegt, um es als einen Rückgabewert durch den Code Aufruf des Unter gesehen werden..

Der Aufruf zu _fact in Hauptwerk in genau der gleichen Weise wie der rekursive Aufruf zu die _fact innerhalb der Unter _fact selbst . Die einzige verbleibende wenig neue Syntax ist: Haupt, nach .sub _main geschrieben. Standardmäßig PIR wird davon ausgegangen, dass Ausführung beginnt mit dem ersten Unter in der Datei. Dieses Verhalten kann geändert durch Kennzeichnung der sub zu start in mit :. Haupt-.

Zusammenstellung zu PBC

Zu kompilieren PIR zu Bytecode , verwenden Sie die Flagge -o, und geben Sie eine Ausgabedatei mit der Erweiterung .pbc..

parrot -o factorial.pbc factorial.pir

PIR vs. PASM

PIR können ,indem Sie in zu PASM gedreht werden durch Laufen:

parrot -o hello.pasm hello.pir

Das PASM für die endgültige Beispiel sieht wie folgt aus:

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

PASM tut nicht verarbeitet Register zuweisung oder bietet keine Unterstützung für die genannten Register. Es hat auch nicht die .sub und .end Richtlinien, anstatt sie zu ersetzen mit einem Etikett zu Beginn der Anleitung.



Advertisements