Hoe is Befunge ontstaan?
Befunge is ontworpen door Chris Pressey. Chris Pressey bedacht Befunge in 1993 met als doel een taal te definiëren die zo moeilijk mogelijk te compileren is.
Een uitdaging voor compilers is bijvoorbeeld het “p”-commando, waarmee het programma dynamisch kan veranderen tijdens runtime.
Wat is Befunge-93?
Befunge is een esoterische programmeertaal en bestaat uit ASCII-tekens in een 80×25 karaktermatrix. Alle functies worden uitgevoerd op een stack.
Waarschijnlijk het meest unieke element van Befunge-93 programmeren is de programmateller (PC). In bijna alle programmeertalen beweegt de programmateller continu vooruit door het programma, af en toe springend naar een andere locatie in de code (maar altijd vooruitgaand). Maar in Befunge-93 gelden andere regels voor de PC. Deze kan vooruit, achteruit, links of rechts bewegen.
Een Befunge-93 programma wordt behandeld als een 80×25 torus (een pagina die rond de randen oprolt) van ASCII-tekst. Bepaalde commando’s veranderen de richting van de voortgang van de PC. Standaard wijst de PC naar de linkerbovenhoek van het programma en beweegt van links naar rechts. Elk commando in Befunge-93 is een enkel karakter, net als de grootste eenheid van data die gespecificeerd kan worden in de broncode van het programma;
Befunge-93 programma’s hebben een maximale totale grootte van 80×25 commando’s en databytes. Er zijn geen runtime-variabelen, alleen een enkele runtime stack.
Befunge-93 programma’s kunnen zichzelf wijzigen. Vanwege de tweedimensionale aard van de PC, laten ze ook zeer grillige code toe.
De stack
Vergelijkbaar met Forth en PostScript, ondersteunt Befunge-93 een LIFO, Reverse Polish Notation (RPN of Postfix) stack van ondertekende lange gehele getallen (elke cel van de stack kan net zo veel bevatten als een ondertekend lang geheel getal in de C-taal op hetzelfde platform). De operatie om een waarde op de stack te plaatsen wordt een “push” genoemd, en de operatie om een waarde van de stack te halen wordt een “pop” genoemd. De cijfers van 0 tot 9 zijn geldige Befunge-93 commando’s die hun respectievelijke waarden op de stack duwen. Een dubbele aanhalingsteken ” activeert de stringmodus, waarbij de ASCII-waarde van alle tekencellen op de stack wordt gezet tot een andere ” wordt gevonden.
Om een getal groter dan 9 op de stack te plaatsen, moeten berekeningen worden uitgevoerd met getallen kleiner dan of gelijk aan 9. In elke andere taal zou dit een probleem zijn. In Befunge-93 is het een plezier. Bijvoorbeeld, om ‘123’ op de stack te plaatsen, zou je 9, 9, dan vermenigvuldigen (waardoor 81 overblijft), dan 7, 6, dan vermenigvuldigen (waardoor 81 en 42 overblijven), dan optellen (wat resulteert in 123.): 9976+. Dit gaat er natuurlijk vanuit dat de PC begint bij of voor de eerste 9 en naar rechts werkt. Als dit gedeelte een volledig Befunge-93 programma vertegenwoordigt, is deze veronderstelling correct: de PC begint linksboven in de torus en is aanvankelijk gericht naar rechts. Als de stack leeg is wanneer je iets van de stack haalt, hoef je niet bang te zijn voor een onderloop! Er wordt eenvoudig een waarde van 0 op de stack gezet.
De programmateller in detail
Er zijn 5 commando’s die onvoorwaardelijk de richting van de PC bepalen:
- > Verplaats de PC naar rechts
- < Verplaats de PC naar links
- v Verplaats de PC naar beneden
- ^ Verplaats de PC naar boven
- ? Verplaats de PC in een willekeurige richting
Als de PC de “rand” van het programma raakt, gaat het gewoon verder aan de andere kant.
Vertakkingen
De standaard ‘if’-verklaring in Befunge-93 is ofwel _ of |, afhankelijk van hoe je wilt vertakken. Beide verklaringen nemen een waarde van de stack, controleren of deze waar is (niet-nul), en veranderen de richting van de PC dienovereenkomstig:
- _ Gedraagt zich als < als de waarde waar is of > als deze onwaar is
- | Gedraagt zich als ^ als de waarde waar is, of als v als deze onwaar is
“while”-lussen kunnen worden gemaakt door een “if” in een oneindige lus in te voegen.
Bijvoorbeeld _@ Dit programmastuk verwijdert alle niet-nulwaarden van de stack en de eerste nulwaarde, en verlaat vervolgens [@ is het exit commando].
Input
- & Haalt een numerieke waarde (decimaal) van de standaard invoer en zet deze op de stack
- ~ haalt het volgende ASCII-teken van standaard invoer en zet dit op de stack.
Bijvoorbeeld,
- &, geeft “A” weer wanneer de gebruiker “65” invoert, en…
- ~. geeft “65 ” weer wanneer de gebruiker “A” invoert.
Output
- . Neemt een waarde van de stack en geeft deze weer als een decimaal getal gevolgd door een spatiekarakter
- , Haalt een waarde van de stack, interpreteert deze als de ASCII-waarde van een karakter en geeft dit karakter weer zonder daaropvolgend spatiekarakter
Bijvoorbeeld, 665+*1-, print ASCII 65 (“A”.), en… 665+*1-. print “65”.
Speciale commando’s
# is het ‘brug’ commando… dit zorgt ervoor dat het volgende commando dat normaal zou worden uitgevoerd, wordt overgeslagen en niet wordt uitgevoerd.
Bijvoorbeeld,
- 123…@ zal “3 2 1” uitvoeren
- 123#…@ zal “3 2” uitvoeren
Slim gebruik van # kan leiden tot zeer interessante code!
: is het commando voor dupliceren. Het maakt een kopie van het bovenste element van de stack.
$ Haalt een waarde van de stack, maar doet er niets mee.
Bijvoorbeeld,
- 123.$.@ zal “3 1” uitvoeren
\ wisselt de twee bovenste elementen van de stack om.
Bijvoorbeeld,
- 123…@ zal “2 3 1” uitvoeren
` is het “groter dan” commando. Het vergelijkt de twee bovenste waarden op de stack en retourneert “1” als de eerste waarde groter is dan de tweede.
Bijvoorbeeld,
- `65 zal “1” uitvoeren
- `25 zal “0”uitvoeren
Zelfmodificatie
De laatste twee commando’s die worden uitgelegd, staan toe dat de inhoud van de torus waarin het programma is opgeslagen kan worden onderzocht en gewijzigd. Dit “speelveld” kan worden gebruikt als een aanvullend geheugen wanneer de stack alleen niet genoeg is. Maar wees voorzichtig, de torus bevat ook het draaiende programma.
g Het g commando controleert de inhoud van het speelveld. Het haalt een y-coördinaat van de stack, dan een x-coördinaat. Het drukt de waarde af die is gevonden op (x, y) op de stack. Als (x, y) een Befunge-93 instructie is, wordt de waarde die op de stack wordt gezet de ASCII-waarde van dat karakter. Vanuit het perspectief van de programmatext bepaalt x de kolom en y de rij; (0, 0) verwijst naar de eerste (meest linkse) kolom en de eerste (bovenste) rij van de programmasource.
p Het p commando verandert de inhoud van het speelveld. Het haalt een y-coördinaat van de stack, dan een x-coördinaat en vervolgens een waarde. De waarde wordt ingevoegd in de torus op positie (x, y). Als het programma het commando op (x, y) op een later tijdstip uitvoert, zal het in de ASCII-tekenset worden geïnterpreteerd als een Befunge-commando met dezelfde waarde die met het p commando daar is geplaatst.
Commando set
Symbool | Commando | Stack – oplopend | Stack (resultaat) |
---|---|---|---|
+ | Optellen | <Waarde1> <Waarde2> | <Waarde1 + Waarde2> |
– | Aftrekken | <Waarde1> <Waarde2> | <Waarde1 – Waarde2> |
* | Vermenigvuldigen | <Waarde1> <Waarde2> | <Waarde1 * Waarde2> |
/ | Delen | <Waarde1> <Waarde2> | <Waarde1 / Waarde2> |
% | Modulus | <Waarde1> <Waarde2> | <Waarde1 mod Waarde2> |
! | niet | <Waarde> | <0 als Waarde <> 0, anders 1> |
‘ | Groter dan | <Waarde1> <Waarde2> | <1 als Waarde1 > Waarde2 , zonder 0> |
> | Rechts | ||
< | Links | ||
^ | Boven | ||
v | Onder | ||
? | Willekeurig | ||
_ | horizontale vertakking | <Waarde> | <> |
| | verticale vertakking | <Waarde> | <> |
“ | stringmodus | ||
: | dupliceren | <Waarde> | <Waarde> <Waarde> |
\ | omwisselen | <Waarde1> <Waarde2> | <Waarde2> <Waarde1> |
$ | verwerpen | <Waarde> | <> |
. | Getal tonen | <Waarde> | toont <Waarde> als getal |
, | Karakter tonen | <Waarde> | toont <Waarde> als karakter |
# | Overslaan | ||
g | Opnemen | <x> <y> | < Waarde of (x,y)> |
p | Plaatsen | <Waarde> <x> <y> | Plaatst Waarde als (x,y) |
& | invoer getal | <Waarde> | |
~ | invoer karakter | <ASCII-Waarde> | |
@ | einde |
Lees meer over Befunge op Wikipedia (en)
De functie Befunge
Bovenin het scherm heb je een schuifknop waarmee je kunt kiezen voor Vertaler of Generator.
Vertaler
Als je ‘vertaler’ kiest verschijnen er twee tekstvelden.
In het eerste tekstveld plaats je de Befunge code.
In het tweede tekstveld plaats tekst die gebruikt moet worden in de code.
Onder Uitvoer zal GC Wizard het resultaat tonen na uitvoer van de code.
Onder Debuggen kun je de stap voor stap uitvoer van de code bekijken.
Generator
Als je ‘generator’ kiest verschijnt er een tekstveld wat je als resultaat wilt krijgen.
Onder Uitvoer zal de programma code worden getoond.