We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Don Giovanni

From Esolang
Jump to navigation Jump to search
This entry is not about Mozart's opera *Don Giovanni*.

Don Giovanni is designed by PSTF and his AI assistant. It is a Turing-complete language, that may be helpful to the design of Lingua Indeterminatum.

Syntax Overview

// Factorial (recursion)
fn factorial(n) {
    if n <= 1 {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

// Fibonacci (double recursion)
fn fib(n) {
    if n <= 1 {
        return n;
    } else {
        return fib(n - 1) + fib(n - 2);
    }
}

// Higher-order function (closure)
fn make_adder(x) {
    fn adder(y) {
        return x + y;
    }
    return adder;
}

let add5 = make_adder(5);
print(add5(10));  // 15

// Loop (while) – ensures Turing completeness
let i = 0;
while i < 10 {
    print(i);
    i = i + 1;
}

print(factorial(5));  // 120
print(fib(10));       // 55

// Floats
let pi = 3.14159;
let radius = 5.0;
let area = pi * radius * radius;
print(area);   // 78.53975

// Lists
let fruits = ["apple", "banana", "cherry"];
print(fruits[1]);           // banana
fruits[1] = "blueberry";
print(fruits[1]);           // blueberry

// Nested lists & indexing
let matrix = [[1, 2], [3, 4]];
print(matrix[0][1]);        // 2

// Characters (with escapes)
let newline = '\n';
let tab = '\t';
print('A');                 // A
print('Hello'[0]);          // H (strings are indexable)

// Built-in functions: len() and push()
let numbers = [1, 2, 3];
print(len(numbers));        // 3
push(numbers, 4);
print(numbers[3]);          // 4

// All mixed together
let mixed = [1, 2.5, "three", 'x'];
print(mixed[2]);            // three

EBNF Definition

(* ------------------------------------------------------------------
   Don Giovanni Programming Language – Complete EBNF (final)
   ------------------------------------------------------------------ *)

program         = { statement } .

(* ----- Statements ------------------------------------------------- *)

statement       = let_stmt
                | assign_stmt
                | if_stmt
                | while_stmt
                | return_stmt
                | print_stmt
                | function_def
                | block
                | expression ";" .

let_stmt        = "let" identifier "=" expression ";" .
assign_stmt     = lvalue "=" expression ";" .
lvalue          = identifier
                | expression "[" expression "]" .

if_stmt         = "if" expression block [ "else" block ] .
while_stmt      = "while" expression block .
return_stmt     = "return" expression ";" .
print_stmt      = "print" "(" expression ")" ";" .

function_def    = "fn" identifier "(" [ identifier { "," identifier } ] ")" block .
block           = "{" { statement } "}" .

(* ----- Expressions (precedence, low → high) ---------------------- *)

expression      = logical_or .

logical_or      = logical_and { "||" logical_and } .
logical_and     = bitwise_or { "&&" bitwise_or } .

bitwise_or      = bitwise_xor { "|" bitwise_xor } .
bitwise_xor     = bitwise_and { "^" bitwise_and } .
bitwise_and     = shift { "&" shift } .

shift           = additive { ( "<<" | ">>" ) additive } .

additive        = multiplicative { ( "+" | "-" ) multiplicative } .

multiplicative  = power { ( "*" | "/" | "%" | "//" ) power } .

(* Exponentiation is right‑associative; this EBNF is syntactic,
   the implementation enforces right‑associativity. *)
power           = unary { "**" unary } .

unary           = ( "-" | "!" | "~" ) unary
                | postfix .

postfix         = primary { "[" expression "]"
                          | "(" [ expression { "," expression } ] ")"
                          } .

(* ----- Primary expressions ---------------------------------------- *)

primary         = integer_literal
                | float_literal
                | string_literal
                | character_literal
                | "true" | "false" | "nil"
                | list_literal
                | identifier
                | "(" expression ")" .

list_literal    = "[" [ expression { "," expression } ] "]" .

(* ----- Lexical tokens --------------------------------------------- *)

integer_literal = digit { digit } .
float_literal   = digit { digit } "." digit { digit }
                | "." digit { digit } .

string_literal  = '"' { string_char | escape_sequence } '"' .
character_literal = "'" ( printable_char | escape_sequence ) "'" .

identifier      = ( letter | "_" ) { letter | digit | "_" } .

escape_sequence = "\" ( "n" | "t" | "\\" | "\"" | "'" ) .

comment         = "//" { any_char - newline } newline .

(* Helpers *)
digit           = "0" | "1" | … | "9" .
letter          = "A" | … | "Z" | "a" | … | "z" .
string_char     = ? any char except backslash or double-quote ? .
printable_char  = ? any char except backslash or single-quote ? .

Implementations

Don Giovanni/Implementations

Example

Factorial

Shown above.

Hello, World!

print("Hello, World!")

A+B Problem

// A+B: function that adds two numbers and prints the result
fn add(a, b) {
    return a + b;
}

let result = add(5, 7);
print(result);   // 12

// Or directly:
print(add(3.5, 2.7));  // 6.2 (floats work too)

Prime Number Detector

fn is_prime(n) {
    if n < 2 {
        return false;
    }
    let i = 2;
    while i * i <= n {
        if n % i == 0 {
            return false;
        }
        i = i + 1;
    }
    return true;
}

print(is_prime(17));  // true
print(is_prime(18));  // false

// Print all primes up to 30
let x = 2;
while x <= 30 {
    if is_prime(x) {
        print(x);
    }
    x = x + 1;
}
// Output: 2 3 5 7 11 13 17 19 23 29

Greeting

print("What is your name?");
let name = read();
print("Hello, " + name + "!");

FizzBuzz by Bitwise

// Use bit flags to track conditions
let FLAG_FIZZ = 1;
let FLAG_BUZZ = 2;

fn check(n) {
    let flags = 0;
    if n % 3 == 0 { flags = flags | FLAG_FIZZ; }
    if n % 5 == 0 { flags = flags | FLAG_BUZZ; }
    return flags;
}

let i = 1;
while i <= 15 {
    let f = check(i);
    if f == 0 {
        print(i);
    } else {
        if f & FLAG_FIZZ { print("Fizz"); }
        if f & FLAG_BUZZ { print("Buzz"); }
    }
    i = i + 1;
}

See Also

Categories