From Esolang
Jump to navigation Jump to search

Volatile is an esoteric programming language invented by User:A that can only push random numbers onto an unbounded stack that can push unbounded numbers. It is inspired by Keg; 7 of the 7 instructions are borrowed from Keg.


~: Push a random number in any range of numbers. The range is determined by what the implementors like.
+: Pop 2 values and push the sum of the 2 values
-: Like +, but subtracts
*: Multiply
/: Divide. 0-division will result in an error.
:: Duplicate the top of the stack
(...): Execute ... inside a while loop when the top of the stack is not 0

Debugging features (not part of the language)

This instruction is frequently used in these examples below. However, they are examples and are expected to be understood by the readers.

.: Output the top of the stack, without popping

It is quite obvious that it does not have a discard operation.


These examples may randomly fail due to Volatile being non-deterministic.

Discard the top element of the stack


Increment top of stack


Decrement top of stack


Create an error

You can definitely be sure on this one.


Square top of the stack


NOT the top of the stack


Display the word "Hi"


Note: It only prints the ASCII values of the letters H and i (72 and 105 respectively)

Hello, world! program

This program is created mechanically, see the code.


Infinite loop


Looping counter


Number tricks

You obviously cannot wish that the random operation("~") will push the number that you want. (You have to be very lucky.)

So, you need a technique that reverses this probability. (Getting a number that you don't want is highly unlikely.)

You can use these code snippets to push 0 or 1 onto the stack.

To push 0(it definitely will not cause an error): ~:-

To push 1(not 100% deterministic; 0-division exception): ~:/

Another way to push 1(crashes in a different manner(array index out of bounds exception in Java interpreter, no-op in Python interpreter)): ~(:/~:-)+

Also, to represent larger integers(like 4), you only have to add by 1's. (Split 4 into 1+1+1+1, and do the push-1 operations.)

Almost every Volatile program relies on duplicating the top of the stack and pushing random numbers.

How to discard the top of the stack

It seems impossible to discard the top of the stack using only numeric operations. However, what we need is just a way to ignore the top of the stack.

The way to achieve this is to multiply the top of the stack by 0(recycling the top-stack number) and add. (This deletes the top-of stack 0 and preserves the bottom-of stack value.)

Computational Class

Volatile is Turing-complete. See the talk page for details.

Python Interpreter

#Volatile Interpreter

import random, sys

source = input()
stack = []

push = stack.append

ip = 0
loop_mode = False
loops = []

while ip < len(source):
    char = source[ip]

    if loop_mode:
        if char == "(":
            loop_mode = False
            ip += 1; continue

    if char == "~": push(random.randint(-sys.maxsize, sys.maxsize))
    elif char in "+-/*":
        a, b = stack.pop(), stack.pop()
    elif char == ":": push(stack[-1])
    elif char == ".": print(*[chr(stack[-1]) if 10 <= stack[-1] <= 256 else stack[-1]])
    elif char == "(": loop_mode = stack[-1] == 0; loops.append(ip)
    elif char == ")":
        if stack[-1] != 0:
            ip = loops[-1] + 1
    else: continue

    ip += 1

(Another) Python 3 interpreter

Implements the spec fully with support for unbounded numbers and nested loops.

# Python interpreter for Volatile
# https://esolangs.org/wiki/Volatile
# No rights reserved

import random
import sys

rand = lambda: random.randint(-(2**31), (2**31)-1)

def pop(stack, k=0):
	if not stack:
		raise IndexError("stack empty")
	if k:
		return stack[-1]
	return stack.pop()

def _op(stack, f, d):
	b = pop(stack)
	a = pop(stack)
	if d and not b:
		raise ArithmeticError("division by zero")
	stack.append(f(a, b))

def op(f, d=0):
	return lambda stack: _op(stack, f, d)

cmd = {
	"~": lambda stack: stack.append(rand()),
	"+": op(lambda a, b: a + b),
	"-": op(lambda a, b: a - b),
	"*": op(lambda a, b: a * b),
	"/": op(lambda a, b: a // b, 1),
	":": lambda stack: stack.append(pop(stack, 1)),
	".": lambda stack: print(pop(stack, 1)),

def volatile_eval(ast, stack=[]):
	for x in ast:
		if isinstance(x, list):
			while pop(stack, 1):
				volatile_eval(x, stack)
	return stack

def parse(s):
	st = [[]]
	for c in s:
		if c == "(":
		elif c == ")":
			x = st.pop()
			if not st:
				raise SyntaxError("unbalanced parentheses")
		elif c in "~+-*/:.":
	if len(st) > 1:
		raise SyntaxError("unbalanced parentheses")
	return st.pop()

if __name__ == "__main__":
	if len(sys.argv) < 2 or \
	   (sys.argv[1] == "-f" and len(sys.argv) != 3) or \
	   (sys.argv[1] != "-f" and len(sys.argv) != 2):
		print("usage: %s {CODE | -f FILE}" % sys.argv[0])
	if sys.argv[1] == "-f":
		with open(sys.argv[2]) as f:
			code = f.read()
		code = sys.argv[1]
		ast = parse(code)
		stack = volatile_eval(ast)
		if stack:
			print("stack:", end=" ")
			for x in stack[:-1]:
				print(x, end=" ")
			print("|%d|" % stack[-1], end="")
	except Exception as ex:

More Interpreters

CGCC User Lyxal asked a question on codegolf.stackexchange.com to create Volatile interpreters. Here's the question: https://codegolf.stackexchange.com/questions/191573/interpret-volatile?r=SearchResults.