Windmill

From Esolang
Jump to navigation Jump to search
The Windmill logo

Windmill is a branchless programming language created by user:RainbowDash on 11/20/2024. Windmill supports all normal mathematical expressions such as 5*(2>1).

Windmill operates in a circular fashion, meaning that when the program reaches the end, it loops back to the starting point. You can define the starting point by marking it with a colon :. After the first loop, the program counter will jump to the line marked with the colon and continue from there.


Here’s an example of how you can use it to create a counter that counts up to 5.

This is the area where you can initialize variables.
i = 0
:This is where the program will start after the first loop
i = i+1
print i
halt = i==5

Variables

In Windmill, variables can only store numbers and are not case-sensitive.

Windmill also includes two special variables for increased functionality: IO and Halt.

  • When IO is set to 0, input and output instructions are disabled.
  • When Halt is set to 1, the program halts.


To initialize a variable, simply write the variable name followed by an assignment to a value.

a = 5
b = 5
c = a+b
print c
halt = 1

It is important to make a halting statement in your code or else it will run in an infinite loop forever.


IO

There are 2 instructions in windmill that act as inputs and outputs.

  • Print - Prints the value of a variable to the console. If the value is surrounded in quotes, it prints the value as a string instead of a number.
  • Prompt - Takes input from the user, if the input is a number it gets converted to a number. However, if the input is text it, the first letter gets converted to ASCII then stores it in the variable.


Here is a simple CAT program to demonstrate the use of these instructions that store the values in a variable A.

Prompt A
Print A
Halt = 1

Computational class

It is unknown whether this language is Turing-complete.

Example programs

High low number guessing game

a = 76 
b = 12
c = 0
i = 0
starting = 0
gate = 1
reversegate = 0

:start

i = ((i+1)*gate) + i*reversegate
b = (b+(2 * a)*gate) + b*reversegate
c = (c+(a + b)*gate) + c*reversegate
a = ((5 + b) % 256*gate) + a*reversegate
b = (c % 256*gate) + b*reversegate
c = (0*gate) + c*reversegate

io = starting==0
print "Guess a random number, higher or lower"
starting = 1
io = 1

prompt x
higher = x>a
lower = x<a
equal = x==a

io = higher==1
print "Too high!"
gate = 1 - higher==1
reversegate = 1 - higher!=1
io = lower==1
print "Too low!"
gate = 1 - lower==1
reversegate = 1 - lower!=1
io = equal==1
print "Right on the money! Guess the next number."
gate = equal==1
reversegate = equal!=1
io = 1

halt = i>5

Defined operators

In order to implement windmill in a coding language you need to define these operators. Extra operators are allowed but not recommended.

  • + Addition
  • - Subtraction
  • / Division
  • * Multiplication
  • % Modulus
  • < Less than
  • > Greater than
  • <= Less than or equal
  • >= Greater than or equal
  • == Equal
  • != Not equal

JS implementation

function Windmill(prgm) {
  prgm = prgm.split('\n').map(line => line.replace(/\t/g, ' ').trim());

  prgm = prgm.map(line => {
    if (line.trim().toLowerCase().startsWith("prompt")) {
      return line; // Do not modify lines starting with "prompt"
    }
    return line.replace(/^(\S+)(.*)/, (match, firstWord, restOfLine) => {
      return firstWord + restOfLine.replace(/(\b[a-zA-Z]+\b)|("[^"]*")/g, (word, variable, quotedString) => {
        if (quotedString) {
          return quotedString; // Preserve quoted strings
        }
        return `vars['${variable}']`; // Replace variables
      });
    });
  });

  let vars = { io: 1, halt: 0 }; // Initialize variables with default values
  let firstLoop = false;
  const checkpointIndex = prgm.findIndex(line => line.trim().startsWith(':'));

  while (vars['halt'] !== 1) { // Loop until halt is set to 1
    for (let i = 0; i < prgm.length; i++) {
      if(i < checkpointIndex && firstLoop){
        continue;
      }
      let args = prgm[i].split(" ");
      if (args.length > 1) {
        if (args[0].toLowerCase() === "print") {
          // Print only if IO is enabled
          if (vars['io'] !== 0) {
            let expression = args.slice(1).join(' ');
            let result;
            if (/^".*"$/.test(expression)) {
              result = expression.slice(1, -1);
            } else {
              result = eval(expression);
            }
            console.log(result);
          }
        } else if (args[0].toLowerCase() === "prompt") {
          // Handle prompt input only if IO is enabled
          if (vars['io'] !== 0) {
            let varName = args[1].toLowerCase();
            let userInput = prompt();
            if (!isNaN(userInput)) {
              vars[varName] = Number(userInput); 
            } else {
              vars[varName] = userInput[0].charCodeAt(0);
            }
          }
        } else {
          let index = args.indexOf("=");
          if (index !== -1) {
            let result = args.slice(index + 1).join('');
            vars[args[0].toLowerCase()] = +eval(result);
          }
        }
      }
    }
    firstLoop = true;
  }
  return vars;
}