Beatnik is an esoteric stack-based language:
http://cliffle.com/esoterica/beatnik.html(read the link first, otherwise everything coming below is completely useless.)
And since I was bored last night, I wrote a simple (and quite dumb) interpreter for it.
It has no practical use whatsoever, but was fun to write and test.
Alas, here's the code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
class Interpreter(object):
def __init__(self, filepath):
f = open(filepath, 'r')
self.code = f.read().replace('\n', ' ').split(' ')
f.close()
self.pc = 0
self.stack = []
self.running = True
self.run()
def run(self):
max_pc = len(self.code) - 1
while self.running and 0 <= self.pc < max_pc:
self.action()
def action(self):
score = self.get_score(self.code[self.pc])
if score < 5:
self.mock()
self.pc += 1
elif score == 5:
self.push_next_word()
elif score == 6:
self.pop()
self.pc += 1
elif score == 7:
self.add()
self.pc += 1
elif score == 8:
self.get_character()
self.pc += 1
elif score == 9:
self.put_character()
self.pc += 1
elif score == 10:
self.substract()
self.pc += 1
elif score == 11:
self.swap()
self.pc += 1
elif score == 12:
self.duplicate()
self.pc += 1
elif score == 13:
self.skip_fz()
elif score == 14:
self.skip_fnz()
elif score == 15:
self.skip_bz()
elif score == 16:
self.skip_bnz()
elif score == 17:
self.halt()
elif 18 <= score <= 23:
self.dont_mock()
self.pc += 1
else:
self.applause()
self.pc += 1
def get_score(self, word):
"""
Get the score of a word.
"""
# scores taken from
# https://en.wikipedia.org/wiki/Scrabble_letter_distributions
scores = {'l': 1, 's': 1, 'u': 1, 'n': 1, 'r': 1, 't': 1, 'o': 1,
'a': 1, 'i': 1, 'e': 1,
'g': 2, 'd': 2,
'b': 3, 'c': 3, 'm': 3, 'p': 3,
'f': 4, 'h': 4, 'v': 4, 'w': 4, 'y': 4,
'k': 5,
'j': 6, 'x': 6,
'q': 7, 'z': 7
}
ret = 0
for char in word.lower():
if char in scores:
ret += scores[char]
return ret
def mock(self):
"""
Mock the user.
"""
print 'You are mocked now.'
def push_next_word(self):
"""
Push the word directly after the program counter and skip it.
"""
if len(self.code) > self.pc:
self.stack.append(self.get_score(self.code[self.pc+1]))
self.pc += 2
def pop(self):
"""
Pop the top number of the stack and discard it.
"""
if len(self.stack) >= 1:
self.stack.pop()
def add(self):
"""
Add the top two numbers of the stack, remove them and push the result.
"""
if len(self.stack) >= 2:
result = self.stack.pop() + self.stack.pop()
self.stack.append(result)
def get_character(self):
"""
Get a character from the user and push its value on the stack.
"""
char = ''
while char == '':
temp = raw_input()
if len(temp) == 1:
char = temp
self.stack.append(int(char))
def put_character(self):
"""
Pop a number off the stack and output the corresponding character.
"""
if len(self.stack) >= 1:
print chr(self.stack.pop()),
def substract(self):
"""
Substract the top two values from the stack and push the result.
"""
if len(self.stack) >= 2:
temp = self.stack.pop()
result = self.stack.pop() - temp
self.stack.append(result)
def swap(self):
"""
Swap the top two values on the stack.
"""
if len(self.stack) >= 2:
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a)
self.stack.append(b)
def duplicate(self):
"""
Duplicate the top value on the stack.
"""
if len(self.stack) >= 1:
self.stack[-1] *= 2
def skip_fz(self):
"""
Skip n+1 words forward if the top value is zero, where n is
the next word's value.
"""
if len(self.stack) >= 1 and len(self.code) > self.pc:
if self.stack[-1] == 0:
self.pc += self.get_score(self.code[self.pc+1]) + 1
def skip_fnz(self):
"""
Skip n+1 words forward if the top value is not zero, where n is
the next word's value.
"""
if len(self.stack) >= 1 and len(self.code) > self.pc:
if self.stack[-1] != 0:
self.pc += self.get_score(self.code[self.pc+1]) + 1
def skip_bz(self):
"""
Skip n words backward if the top value is zero, where n is
the next word's value.
"""
if len(self.stack) >= 1 and len(self.code) > self.pc:
if self.stack[-1] == 0:
self.pc -= self.get_score(self.code[self.pc+1])
def skip_bnz(self):
"""
Skip n words backward if the top value is not zero, where n is
the next word's value.
"""
if len(self.stack) >= 1 and len(self.code) > self.pc:
if self.stack[-1] != 0:
self.pc -= self.get_score(self.code[self.pc+1])
def halt(self):
"""
Stop the program.
"""
self.running = False
def dont_mock(self):
"""
Don't mock the user.
"""
print 'You are not mocked now.'
def applause(self):
"""
Applaude the user.
"""
print 'APPLAUSE!'
if __name__ == '__main__':
interpreter = Interpreter(sys.argv[1])
And here is a Hello World:
k qqqqqqkkkkkk qg
k qqqqqqqqqqqqqqb qg
k qqqqqqqqqqqqqqqb qg
k qqqqqqqqqqqqqqqb qg
k qqqqqqqqqqqqqqqbb qg
k qqqqf qg
k qqqqqqqqqqqqb qg
k qqqqqqqqqqqqqqqbb qg
k qqqqqqqqqqqqqqqqg qg
k qqqqqqqqqqqqqqqb qg
k qqqqqqqqqqqqqqg qg
k qqqqk gq
Of course I cheated, the real challenge would be to use real words.
Have fun.