Die Deutsche Programmiersprache

From Esolang
Jump to navigation Jump to search

Die Deutsche Programmiersprache (DDP, English: The German programming language) is a imperative and modular joke programming language by NotLe0n and bafto, which was designed so that programs written in it read like almost proper German.

Die Deutsche Programmiersprache
Paradigm(s) imperative, modular
Designed by NotLe0n and bafto
Appeared in 2022
Computational class Turing complete
Major implementations Original
File extension(s) .ddp

It was created to show the absurdity of using natural language to write programs.

The compiler and language server source code can be found on GitHub

The Bedienungsanleitung (documentation) is a good starting point to get to know DDP; you can also find installation instructions there.

The Playground makes it possible to try out DDP without having to install the compiler.

Language Overview

Comments are written between square brackets and are used in the following examples to translate DDP to pseudo-code.

Expressions

Every expression in DDP produces a value of fixed type and ends in a dot.

[ 2 + 2; ]
2 plus 2.

[ ToNumber("22" + "4"); ] 
("22" verkettet mit "4") als Zahl. 

[ ToFloat(2 << 2) == 2^3; ]
(2 um 2 Bit nach links verschoben) als Kommazahl gleich 2 hoch 3 ist. 

[ true && 2 >= 3 || "test" == "te" + "st"; ]
wahr und 2 größer als, oder 3 ist oder "test" gleich "te" verkettet mit "st" ist. 

Variables

Variables also have a fixed type.

[ Include "Duden/Ausgabe"; ]
Binde "Duden/Ausgabe" ein.

[ Number z = 22; ]
Die Zahl z ist 22.

[ Println(z); => "22\n" ]
Schreibe die Zahl z auf eine Zeile.

[ z = 'B'; => Error: Types don't match ]
Speichere 'B' in z.
[z = ToNumber('B'); with cast alright] 
Speichere 'B' als Zahl in z.

[ String t = "Hallo Welt!\n"; ]
Der Text t ist "Hallo Welt!\n".
Schreibe den Text t. [output]
Schreibe t. [same output]

Lists

DDP also has lists, but it doesn't have fixed sized arrays. Lists are 1-Based arrays, so the index 1 is the first Element of the list.

[ NumberList liste = { 23, 12, 3, 7, 8 } ]
Die Zahlen Liste liste ist eine Liste, die aus 23, 12, 3, 7, 8 besteht.

[ Print(length(liste)) => "5" ]
Schreibe (die Länge von liste).

[ Print(liste[0]) => "23" ]
Schreibe (liste an der Stelle 1).

[ Print(liste[2...5] => "12, 3, 7, 8" ]
Schreibe (liste von 2 bis 5).

[ Print(liste[3...4] + liste[1...2]) => "3, 7, 23, 12" ]
Schreibe (liste von 3 bis 4 verkettet mit liste von 1 bis 2).

Instruction Blocks

In DDP, multiple instructions can be grouped together in a block.

:
    Schreibe "Ich bin in einem Block".
    Die Zahl zahl ist 2.
    :
        [ Output: 2 ]
        Schreibe zahl.
    :
        Die Zahl zahl ist 3.
        [ Output: 3 ]
        Schreibe zahl.

[ Error: zahl was declared in a block and isn't avalible ]
Schreibe zahl.

As you can see, each block begins with a ":". Variables are transferred to sub-blocks, but overshadow new declarations with the same name old declarations.

Since {} are not symbols of German texts, the Indentation depth (4 spaces or 1 tab) is used to determine when a block is finished.

If statements

For simple branches, DDP offers If statements.

Wenn 1 gleich 2 ist, dann:
    Schreibe "Wenn".
Wenn aber 1 ungleich 2 ist, dann: 
    Schreibe "Wenn-aber".
Sonst:
    Schreibe "Sonst".

Of course, this can also be done without instruction blocks, but only for single instructions.

Wenn 1 gleich 2 ist, Schreibe "Wenn".
Wenn aber 1 ungleich 2 ist, Schreibe "Wenn-aber". Sonst Schreibe "Sonst".

Loops

While Loops

Die Zahl iterator ist 3.
Solange iterator größer als, oder 0 ist, mache:
    Schreibe iterator auf eine Zeile.
    Verringere iterator um 1.

Do-While Loops

Mache:
    Schreibe "Iteration!".
Solange 2 gleich 3 ist.

For Loops

[Output: 12345]
Für jede Zahl i von 1 bis 5, mache:
    Schreibe i.

[Output: 135]
Für jede Zahl i von 1 bis 5 mit Schrittgröße 2, mache:
    Schreibe i.

[Backwards]
[Output: 54321]
Für jede Zahl i von 5 bis 1 mit Schrittgröße -1, mache:
    Schreibe i.

[Iterating over a list]
[Ausgabe: hihi2]
Die Text Liste tl ist eine Liste, die aus "hi", "hi2" besteht.
Für jeden Text t in tl, mache:
    Schreibe t.

Repetitions

So that you don't always have to write a long for loop there are also repetitions:

Wiederhole:
    Schreibe "hi".
10 Mal.

Single Instructions

Just like with if statements, this can all be done with single instructions.


Solange 1 gleich 2 ist, Schreibe "test".

Für jede Zahl i von 1 bis 5, Schreibe i.

Für jeden Text t in tl, Schreibe t.

Schreibe "hi" 10 Mal.

Functions

Functions are by far the most important feature of DDP, because they allow you to turn almost any German sentence or expression into code.

This is due to the way they are called, namely via so-called aliases.

[
    String foo(String t, int bar, int baz) {
        return t + to_string(bar + baz);
    }
]
Die Funktion foo mit den Parametern t, bar und baz vom Typ Text, Zahl und Zahl, gibt einen Text zurück, macht: 
    Der Text ergebnis ist t verkettet mit (bar plus baz) als Text.
    Gib ergebnis zurück.
Und kann so benutzt werden:
    "<t> verbunden mit <bar> addiert zu <baz>"

[ print(foo("Ergebnis: ", 2, 15)); ]
Schreibe ("Ergebnis: " verbunden mit 2 addiert zu 15).

As you can see, the function foo was called like a normal German expression without violating the grammatical rules.

Functions are a very big topic in DDP and this small example shows only a fraction of their complex syntax.

For more details, I strongly recommend reading this article from the documentation thoroughly, or at least skimming the examples.

Modules

In DDP, source code is organized into modules, where a module is simply a source file.

In fact, all of the examples above already have used the Module "Duden/Ausgabe" to be able to use the Schreibe x function.

Binde "Duden/Ausgabe" ein.
Schreibe "Hallo Welt".

include.ddp:

Binde Schreibe_Zahl aus "Duden/Ausgabe" ein.

Die öffentliche Zahl zahl ist 22.
Die öffentliche Funktion bar gibt nichts zurück, macht:
    Schreibe zahl.
Und kann so benutzt werden:
    "Rufe bar auf"

Die Zahl zahl2 ist 23.

test.ddp

Binde "include" ein.

Schreibe zahl auf eine Zeile.
Rufe bar auf.
Schreibe zahl2 auf eine Zeile. [Error: zahl2 doesn't exist]

Examples

More examples can be found on GitHub

FizzBuzz

Binde "Duden/Ausgabe" ein.
Binde ist_teilbar aus "Duden/Mathe" ein.

Für jede Zahl i von 1 bis 100, mache:
    Wenn i durch 3 teilbar ist und i durch 5 teilbar ist, Schreibe den Text "FizzBuzz" auf eine Zeile.
    Sonst:
        Wenn i durch 3 teilbar ist, Schreibe den Text "Fizz" auf eine Zeile.
        Wenn aber i durch 5 teilbar ist, Schreibe den Text "Buzz" auf eine Zeile.
        Sonst Schreibe die Zahl i auf eine Zeile.

Mandelbrot

[
    Dieses Programm nimmt eine Breite eine Höhe und eine Anzahl an maximalen Iterationen
    und generiert eine Ascii-Bild des Mandelbrot Fractals in der angegebenen Größe.

    Beispiel Ausgabe generiert mit $kddp starte Mandelbrot.ddp 27 18 100

. . . . . . . . . . . . . . . . @ . . . . . . . . . . 
. . . . . . . . . . . . . . . @ @ : . . . . . . . . . 
. . . . . . . . . . . . : . : : @ : : . . . . . . . . 
. . . . . . . . . . . . @ @ @ @ @ @ @ : # . . . . . . 
. . . . . . . . . . . * @ @ @ @ @ @ @ @ : . . . . . . 
. . . . . . : . : . . @ @ @ @ @ @ @ @ @ @ : . . . . . 
. . . . . . : @ @ @ : @ @ @ @ @ @ @ @ @ @ : . . . . . 
. . . . . : @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ . . . . . . 
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ . . . . . . . 
. . . . . : @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ . . . . . . 
. . . . . . : @ @ @ : @ @ @ @ @ @ @ @ @ @ : . . . . . 
. . . . . . : . : . . @ @ @ @ @ @ @ @ @ @ : . . . . . 
. . . . . . . . . . . * @ @ @ @ @ @ @ @ : . . . . . . 
. . . . . . . . . . . . @ @ @ @ @ @ @ : # . . . . . . 
. . . . . . . . . . . . : . : : @ : : . . . . . . . . 
. . . . . . . . . . . . . . . @ @ : . . . . . . . . . 
. . . . . . . . . . . . . . . . @ . . . . . . . . . . 
. . . . . . . . . . . . . . . . : @ . . . . . . . . . 

]

Binde "Duden/Mathe" ein.
Binde "Duden/Texte" ein.
Binde "Duden/Listen" ein.
Binde "Duden/Ausgabe" ein.
Binde "Duden/Laufzeit" ein.

[
    quadrat einer komplexen Zahl mit 3 Produkten
    für den Alias
]
Die Funktion komplexes_quadrat mit den Parametern r und i vom Typ Kommazahlen Referenz und Kommazahlen Referenz, gibt nichts zurück, macht:
    Die Kommazahl summe ist i plus r.
    
    Quadriere r.
    Quadriere i.
    Quadriere summe.

    Die Kommazahl r2 ist r minus i.
    Die Kommazahl i2 ist summe minus (r plus i).
    Speichere r2 in r.
    Speichere i2 in i.
Und kann so benutzt werden:
    "Quadriere <r>i<i>"


[Projeziert den Wert s innerhalb des Intervalls [a1,a2] auf die Folge [b1,b2]]
Die Funktion Intervall_Projektion mit den Parametern s, a1, a2, b1 und b2 vom Typ Kommazahl, Kommazahl, Kommazahl, Kommazahl und Kommazahl, gibt eine Kommazahl zurück, macht:
    Gib b1 plus (((s minus a1) mal (b2 minus b1)) durch (a2 minus a1)) zurück.
Und kann so benutzt werden:
    "<s> von <a1> bis <a2> auf <b1> bis <b2> projeziert"

Die Text Liste args ist die Befehlszeilenargumente.
Wenn die Länge von args kleiner als 4 ist, dann:
    Schreibe "Befehlszeilen Argumente bitte im Format \"<Breite> <Höhe> <Max_Iterationen>\" angeben \n".
    Beende das Programm.

Die Zahl Breite ist (args an der Stelle 2) als Zahl. [breite in ascii zeichen]
Die Zahl Höhe ist (args an der Stelle 3) als Zahl. [höhe in ascii zeichen]

Die Zahl Max_Iterationen ist (args an der Stelle 4) als Zahl. [maximale iterationen]


Die Funktion finde_Anzahl_iterationen mit den Parametern c_r und c_i vom Typ Kommazahl und Kommazahl, gibt eine Zahl zurück, macht:
    Die Zahl iterationen ist 1.
    Die Kommazahl f_r ist c_r.
    Die Kommazahl f_i ist c_i.

    Solange f_r zum quadrat plus f_i zum quadrat kleiner als, oder 4,0 ist und iterationen kleiner als Max_Iterationen ist, mache:
        Quadriere f_r i f_i.
        [Komplexe addition]
        Erhöhe f_r um c_r.
        Erhöhe f_i um c_i.

        Erhöhe iterationen um 1.

    Gib iterationen zurück.
Und kann so benutzt werden:
    "die Anzahl der Mandelbrot-Iterationen von <c_r>i<c_i>"

Die Funktion finde_Farbe mit dem Parameter iterationen vom Typ Zahl, gibt einen Buchstaben zurück, macht:
    Wenn iterationen kleiner als 10 ist, gib '.' zurück.
    Wenn aber iterationen kleiner als 20 ist, gib ':' zurück.
    Wenn aber iterationen kleiner als 50 ist, gib '*' zurück.
    Wenn aber iterationen kleiner als 80 ist, gib '#' zurück.
    Gib '@' zurück.
Und kann so benutzt werden:
    "die Farbe bei <iterationen> Iterationen"

Für jede Zahl y von 1 bis Höhe, mache:
    Für jede Zahl x von 1 bis Breite, mache:
        Die Kommazahl c_r ist (x als Kommazahl) von 0,0 bis (Breite als Kommazahl) auf -2,0 bis 1,0 projeziert.
        Die Kommazahl c_i ist (y als Kommazahl) von 0,0 bis (Höhe als Kommazahl) auf -1,0 bis 1,0 projeziert.

        Die Zahl iterationen ist die Anzahl der Mandelbrot-Iterationen von c_r i c_i.
        [Speichere die Farbe bei iterationen Iterationen in Zeilen an der Stelle y, an der Stelle x.]
        Schreibe (die Farbe bei iterationen Iterationen).
        Schreibe ' '.
    Schreibe '\n'.