NeverGonna
NeverGonna is an esoteric programming language that is designed to look like the famous song "Never Gonna Give You Up".
Syntax
To declare a variable named foo with the value of 2:
we're no strangers to foo gotta make foo 2
To make an if statement checking if foo == "orange", using a user input:
we're no strangers to foo
gotta make foo your heart's been aching but you're too shy to say 'Please type in "orange"' -- get user input
inside we both know foo == "orange" then -- if statement
i just wanna tell you "You did it!"
never gonna let you down -- else
i just wanna tell you "You failed."
never gonna give you up -- end
To add two numbers into a variable named bar:
we're no strangers to bar gotta make bar foo + 1
To make a for loop that prints the numbers 0 through 10:
we're no strangers to foo
gotta make foo 0
we've known foo for 10 -- for loop
i just wanna tell you foo
never gonna give you up -- end for loop
To make a while loop
we're no strangers to foo
we're no strangers to bar
gotta make foo True
a full commitment's what I'm thinking of foo -- while loop (while foo)
gotta make bar your heart's been aching but you're too shy to say 'Please type in "orange"'
inside we both know bar == "orange" then
gotta make foo False
never gonna turn around bar == "" then -- elif
i just wanna tell you "You didn't type anything."
never gonna let you down -- else
i just wanna tell you "You didn't type orange."
never gonna give you up
never gonna give you up
i just wanna tell you "You did it!"
The language's syntactical aspects shall be elucidated in an Extended Backus-Naur Form (EBNF) description:
program := { innerEmptyLine }
, { innerCommandLine | innerEmptyLine }
, [ lastCommandLine | lastEmptyLine ]
;
innerEmptyLine := [ comment ] , newlines ;
lastEmptyLine := [ comment ] ;
innerCommandLine := statement , [ comment ] , newlines ;
lastCommandLine := statement , [ comment ] ;
comment := "--" , { character - newline } ;
statementList := { statementListItem } ;
statementListItem := { innerEmptyLine }
, [ innerCommandLine ]
, { innerEmptyLine }
;
statement := varDeclaration
| varAssignment
| inputExpression
| printCommand
| ifStatement
| forLoop
| whileLoop
;
varDeclaration := "we're no strangers to" , varName ;
varAssignment := "gotta make" , varName , expression ;
printCommand := "i just wanna tell you" , expression ;
ifStatement := ifThenPart
, newlines
, { elseIfPart }
, [ elsePart ]
, endOfStatement
;
ifThenPart := "inside we both know" , expression , "then"
, newlines
, statementList
;
elseIfPart := "never gonna turn around" , expression
, "then"
, newlines
, statementList
;
elsePart := "never gonna let you down"
, newlines
, statmentList
;
forLoop := "we've known" , varName , "for" , expression
, newlines
, statementList
, newlines
, endOfStatement
;
whileLoop := "a full commitment's what I'm thinking of"
, expression
, newlines
, statementList
, newlines
, endOfStatement
;
endOfStatement := "never gonna give you up" ;
expression := booleanValue
| number
| singleQuoteString
| doubleQuoteString
| varName
| inputExpression
| unaryOperator , expression
| expression , binaryOperator , expression
| expression , relationOperator , expression
| "(" , expression , ")"
;
inputExpression := "your heart's been aching but you're too shy to say"
, expression
;
unaryOperator := "+" | "-" | "!" ;
binaryOperator := "+" | "-" | "*" | "/" | "%" | "^"
| "&&" | "||"
;
relationOperator := "==" | "!=" | "<" | "<=" | ">" | ">=" ;
varName := varNameCharacter , { varNameCharacter } ;
varNameCharacter := "a" | ... | "z" | "A" | ... | "Z"
| "_"
| digit
;
booleanValue := "False" | "True" ;
singleQuoteString := "'" , { character - "'" } , "'" ;
doubleQuoteString := '"' , { character - '"' } , '"' ;
number := [ "+" | "-" ] , digit , { digit } ;
digit := "0" | "1" | "2" | "3" | "4"
| "5" | "6" | "7" | "8" | "9"
;
newline := "\n" ;
newlines := newline , { newline } ;
optionalNewlines := { newline } ;
Commands
The arithmetic sign and logical NOT operators intrine to form the unary operation set:
| Operator | Operand | Effect |
|---|---|---|
+
| ||
| Boolean | invalid | |
| integer | plus sign | |
| string | invalid | |
-
| ||
| Boolean | invalid | |
| integer | minus sign | |
| string | invalid | |
!
| ||
| Boolean | logical NOT | |
| integer | invalid | |
| string | invalid |
The following binary operations, with respect to the possible operand type combinations, exist:
| Operator | Left operand | Right operand | Effect |
|---|---|---|---|
+
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | addition | |
| integer | string | string concatenation | |
| string | Boolean | invalid | |
| string | integer | string concatenation | |
| string | string | string concatenation | |
-
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | subtraction | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
*
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | multiplication | |
| integer | string | string repetition | |
| string | Boolean | invalid | |
| string | integer | string repetition | |
| string | string | invalid | |
/
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | division | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
%
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | remainder | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
^
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | exponentiation, power | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
&&
| |||
| Boolean | Boolean | logical AND | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | invalid | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
||
| |||
| Boolean | Boolean | logical OR | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | invalid | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | invalid | |
==
| |||
| Boolean | Boolean | equality | |
| Boolean | integer | equality | |
| Boolean | string | equality | |
| integer | Boolean | equality | |
| integer | integer | equality | |
| integer | string | equality | |
| string | Boolean | equality | |
| string | integer | equality | |
| string | string | equality | |
!=
| |||
| Boolean | Boolean | inequality | |
| Boolean | integer | inequality | |
| Boolean | string | inequality | |
| integer | Boolean | inequality | |
| integer | integer | inequality | |
| integer | string | inequality | |
| string | Boolean | inequality | |
| string | integer | inequality | |
| string | string | inequality | |
<
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | less than | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | less than (lexicographic) | |
<=
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | less than or equal to | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | less than or equal to (lexicographic) | |
>
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | greater than | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | greater than (lexicographic) | |
>=
| |||
| Boolean | Boolean | invalid | |
| Boolean | integer | invalid | |
| Boolean | string | invalid | |
| integer | Boolean | invalid | |
| integer | integer | greater than or equal to | |
| integer | string | invalid | |
| string | Boolean | invalid | |
| string | integer | invalid | |
| string | string | greater than or equal to (lexicographic) |
Examples
Hello World
i just wanna tell you "Hello World"
FizzBuzz
we're no strangers to i
gotta make i 0
we've known i for 100
inside we both know i % 15 == 0 then
i just wanna tell you "FizzBuzz"
never gonna turn around i % 3 == 0 then
i just wanna tell you "Fizz"
never gonna turn around i % 5 == 0 then
i just wanna tell you "Buzz"
never gonna let you down
i just wanna tell you i
never gonna give you up
never gonna give you up
Truth-Machine
A truth-machine shall be demonstrated:
we're no strangers to yourInput gotta make yourInput your heart's been aching but you're too shy to say 'Please input 0 or 1' i just wanna tell you yourInput a full commitment's what I'm thinking of yourInput == 1 i just wanna tell you yourInput never gonna give you up
Looping Counter
This program counts from inclusive one (1) to inclusive 100, printing on each line a tally of asterisks (“*”) tantamount to the respective counter state:
we're no strangers to counter gotta make counter 1 we've known counter for 100 i just wanna tell you '*' * counter never gonna give you up
Cat Program
An infinitely repeating cat program is implemented as such:
a full commitment's what I'm thinking of True i just wanna tell you your heart's been aching but you're too shy to say 'Please input a character:' never gonna give you up
99 Bottles of Beer
The following program prints the lyrics of the song “99 Bottles of Beer”:
we're no strangers to number_of_bottles
gotta make number_of_bottles 99
a full commitment's what I'm thinking of number_of_bottles > 0
inside we both know number_of_bottles > 2 then
i just wanna tell you number_of_bottles + ' bottles of beer on the wall,'
i just wanna tell you number_of_bottles + ' bottles of beer.'
i just wanna tell you 'Take one down, pass it around,'
i just wanna tell you number_of_bottles - 1 + ' bottles of beer on the wall.'
i just wanna tell you
never gonna turn around number_of_bottles == 2 then
i just wanna tell you number_of_bottles + ' bottles of beer on the wall,'
i just wanna tell you number_of_bottles + ' bottles of beer.'
i just wanna tell you 'Take one down, pass it around,'
i just wanna tell you number_of_bottles - 1 + ' bottle of beer on the wall.'
i just wanna tell you
never gonna let you down
i just wanna tell you number_of_bottles + ' bottle of beer on the wall,'
i just wanna tell you number_of_bottles + ' bottle of beer.'
i just wanna tell you 'Take one down, pass it around,'
i just wanna tell you 'No bottles of beer on the wall.'
i just wanna tell you
never gonna give you up
gotta make number_of_bottles number_of_bottles - 1
never gonna give you up
Interpreter
- Common Lisp implementation of the NeverGonna programming language.
Computational class
It is easy to implement a 2 register minsky machine in NeverGonna, so it is Turing complete.