Extendable MiniLang
Jump to navigation
Jump to search
Next time you create a language that is computable, write an interpreter for it!
- -- ISLPTNG
Extendable MiniLang is designed by PSTF and his AI friend.
Command Set
Can you believe that? It only has 6 commands!
| Command | Meaning |
|---|---|
| INC x | Increase x by 1. |
| DEC x | Decrease x by 1. |
| JNZ x l | Jump to label if x is not 0. |
| JMP l | Jump to label if 1+1=2. |
| HLT | Halt. |
| OUT x | Print. |
A variable is just a string made of lower alphabets.
Comments are started by a hashtag.
Variables are initially 0.
Label name is just a "variable name" with a colon after it.
Commands by other users
| Command | Meaning |
|---|---|
| JZR x, l | Jump to l if x is 0. |
Examples
3 × 2
# 初始化 INC a INC a INC a # a = 3 (Multiplier) INC b INC b # b = 2 (Multiplicand) # 乘法循环 outer_loop: JNZ b transfer # If b ≠ 0 then transfer a to temp JMP end transfer: DEC b JNZ a copy # Assign temp with a JMP outer_loop copy: DEC a INC temp INC a_copy JMP copy # Copy again restore: JNZ a_copy restore_a # Restore a JMP add_temp restore_a: DEC a_copy INC a JMP restore add_temp: JNZ temp add_to_c # Add temp into c JMP outer_loop add_to_c: DEC temp INC c JMP add_temp end: PRINT c # Output 6 HALT
Interpreter
If you added a command, please update the interpreter.
import sys
class MiniLangInterpreter:
def __init__(self, program):
self.program = program
self.vars = {}
self.labels = {}
self.instructions = []
self.pc = 0 # Program counter
def load(self):
lines = [line.strip() for line in self.program.split('\n')
if line.strip() and not line.strip().startswith('#')]
# 1: collect label
for idx, line in enumerate(lines):
if line.endswith(':'):
label = line[:-1]
self.labels[label] = idx - len(self.labels) # Label is not a command
# 2: interpret the command
for line in lines:
if line.endswith(':'):
continue # Skip over the label
parts = line.split()
self.instructions.append(parts)
def get_var(self, name):
return self.vars.get(name, 0)
def set_var(self, name, value):
self.vars[name] = value
def run(self):
self.load()
while 0 <= self.pc < len(self.instructions):
cmd = self.instructions[self.pc]
op = cmd[0].upper()
try:
if op == "INC":
var = cmd[1]
self.set_var(var, self.get_var(var) + 1)
self.pc += 1
elif op == "DEC":
var = cmd[1]
self.set_var(var, self.get_var(var) - 1)
self.pc += 1
elif op == "JNZ":
var, label = cmd[1], cmd[2]
if self.get_var(var) != 0:
self.pc = self.labels[label]
else:
self.pc += 1
elif op == "JMP": # JMP is the syntax-candy for JNZ
label = cmd[1]
self.pc = self.labels[label]
elif op == "OUT":
var = cmd[1]
print(f"{var} = {self.get_var(var)}")
self.pc += 1
elif op == "HLT":
break
else:
raise RuntimeError(f"Unknown operator: {op}")
except Exception as e:
print(f"Line {self.pc+1} error: {e}")
break
# Run from file or input
if __name__ == "__main__":
if len(sys.argv) > 1:
with open(sys.argv[1], 'r') as f:
code = f.read()
else:
code = sys.stdin.read();
interpreter = MiniLangInterpreter(code)
interpreter.run()