MoreThanZero
(Redirected from MTZ)
- This is still a work in progress. It may be changed in the future.
- This article is not detailed enough and needs to be expanded. Please help us by adding some more information.
![]() |
|
| Designed by | User:DumbEsolangsOrgUser. |
|---|---|
| Appeared in | 2025 |
| Computational class | Unknown |
| Reference implementation | Unimplemented |
MoreThanZero is one of stack-based esoteric programming languages, which just editing the numbers by stack, and can't create useful programms, and it makes MoreThanZero unuseful.
Language Overview
MoreThanZero is character-by-character esoteric programming language using *.morethanzero files (.morethanzero it's just a renamed .txt)
MoreThanZero using this commands:
| Command | Description |
|---|---|
0, 1...
|
Add digit to stack |
<
|
Delete first digit in stack |
>
|
Delete last digit in stack |
+
|
Add all digits in stack, split the result into characters, and change stack to them. |
-
|
subtract all digits in stack, split the result into characters, and change stack to them. |
.
|
Output the stack |
,
|
Input character and put it in stack. If input has more than 1 character or has letters — ignore |
[
|
Output first digit in stack |
]
|
Output last digit in stack |
&
|
Collect all the digits from stack and locally put them into one number and output the number it as ASCII (This command do nothing with stack) |
#
|
Pass next character |
All characters other than 1234567890><+-.,[]&# is comments.
Why "MoreThanZero"?
I using "MoreThanZero" as name and as file extension because it have more than zero stacks
Implementations
Python GUI IDE+File reader+CLI
# morethanzero_tkinter_and_light.py
# Contains two parts in one file for convenience:
# 1) A full tkinter IDE + File runner + Lightweight GUI in a single app (modes switched by buttons)
# 2) A separate small command-line "lightweight" interpreter (starting with "if __name__ == '__main__' and --light" )
#
# Save this file as morethanzero_tkinter_and_light.py and run with:
# python morethanzero_tkinter_and_light.py
# The GUI starts. To run only the tiny CLI runner (minimal footprint), use:
# python morethanzero_tkinter_and_light.py --cli path/to/file.morethanzero
#
# Interpreter implementation follows the MoreThanZero spec from Esolangs: https://www.esolangs.org/wiki/MoreThanZero
# (commands: digits push, < remove first, > remove last, + sum -> stack digits, - subtract -> stack digits, . output stack,
# , input char, [ output first, ] output last, & collect digits->number->print ASCII char, # skip next char)
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import argparse
import threading
import time
class MoreThanZeroInterpreter:
def __init__(self, code, input_text=''):
self.code = code or ''
self.ip = 0
self.stack = [] # list of characters
self.output = []
self.input_text = input_text or ''
self.input_pos = 0
self.skip_next = False
self.max_steps = 1000000
self.steps = 0
def _read_input_char(self):
# obey spec: If input has more than 1 character or has letters — ignore
if self.input_pos >= len(self.input_text):
return None
ch = self.input_text[self.input_pos]
self.input_pos += 1
if len(ch) != 1:
return None
if ch.isalpha():
return None
return ch
def step(self):
if self.ip >= len(self.code):
return False
ch = self.code[self.ip]
# '#' passes next character
if ch == '#':
self.ip += 1 # move to next char
if self.ip < len(self.code):
# skip it
self.ip += 1
return True
if ch.isdigit():
self.stack.append(ch)
elif ch == '<':
if self.stack:
del self.stack[0]
elif ch == '>':
if self.stack:
self.stack.pop()
elif ch == '+':
# Add all digits in stack, split result into characters, change stack
total = 0
for d in self.stack:
if d.isdigit():
total += int(d)
s = str(total)
self.stack = list(s)
elif ch == '-':
# Subtract all digits in stack left-to-right
digits = [int(d) for d in self.stack if d.isdigit()]
if not digits:
result = 0
else:
result = digits[0]
for d in digits[1:]:
result -= d
s = str(result)
self.stack = list(s)
elif ch == '.':
# Output the stack as-is (concatenated)
self.output.append(''.join(self.stack))
elif ch == ',':
c = self._read_input_char()
if c is not None and not c.isalpha() and len(c) == 1:
# spec says: input character and put it in stack. If input has more than 1 character or has letters — ignore
# here we accept single non-letter character (digits or punctuation), but pushing only if it's a digit
# The spec suggests digits in stack, but it says "put it in stack" — we'll push the char as-is.
self.stack.append(c)
elif ch == '[':
if self.stack:
# output first digit in stack
self.output.append(self.stack[0])
elif ch == ']':
if self.stack:
self.output.append(self.stack[-1])
elif ch == '&':
# Collect all digits from stack and form a number, output it as ASCII char.
numstr = ''.join([c for c in self.stack if c.isdigit()])
if numstr:
try:
val = int(numstr)
# guard against out-of-range
if 0 <= val <= 0x10FFFF:
try:
self.output.append(chr(val))
except Exception:
# fallback: append numeric representation in brackets
self.output.append(f'<{val}>')
else:
self.output.append(f'<{val}>')
except Exception:
pass
else:
# other characters are comments
pass
self.ip += 1
self.steps += 1
if self.steps > self.max_steps:
raise RuntimeError('Step limit exceeded (possible infinite loop)')
return True
def run(self, timeout_seconds=None):
start = time.time()
while self.ip < len(self.code):
if timeout_seconds is not None and (time.time() - start) > timeout_seconds:
raise TimeoutError('Execution timed out')
cont = self.step()
if not cont:
break
return ''.join(self.output)
# ------------------ Tkinter GUI ------------------
class MoreThanZeroGUI(tk.Tk):
def __init__(self):
super().__init__()
self.title('MoreThanZero — Interpreter')
self.geometry('900x600')
# Top controls: mode buttons
ctl_frame = tk.Frame(self)
ctl_frame.pack(side=tk.TOP, fill=tk.X)
self.mode_var = tk.StringVar(value='IDE')
for mode in ('IDE', 'File runner', 'Lightweight'):
b = tk.Radiobutton(ctl_frame, text=mode, variable=self.mode_var, value=mode, indicatoron=False, command=self._switch_mode)
b.pack(side=tk.LEFT, padx=4, pady=4)
# Container for frames
container = tk.Frame(self)
container.pack(fill=tk.BOTH, expand=True)
# IDE Frame
self.ide_frame = tk.Frame(container)
self.file_frame = tk.Frame(container)
self.light_frame = tk.Frame(container)
for f in (self.ide_frame, self.file_frame, self.light_frame):
f.place(relwidth=1, relheight=1)
self._build_ide(self.ide_frame)
self._build_file(self.file_frame)
self._build_light(self.light_frame)
self._switch_mode()
def _switch_mode(self):
mode = self.mode_var.get()
if mode == 'IDE':
self.ide_frame.lift()
elif mode == 'File runner':
self.file_frame.lift()
else:
self.light_frame.lift()
def _build_ide(self, frame):
top = tk.Frame(frame)
top.pack(fill=tk.X)
save_btn = tk.Button(top, text='Save', command=self._ide_save)
save_btn.pack(side=tk.LEFT, padx=2, pady=2)
load_btn = tk.Button(top, text='Load', command=self._ide_load)
load_btn.pack(side=tk.LEFT, padx=2, pady=2)
run_btn = tk.Button(top, text='Run', command=self._ide_run)
run_btn.pack(side=tk.LEFT, padx=2, pady=2)
step_btn = tk.Button(top, text='Step', command=self._ide_step)
step_btn.pack(side=tk.LEFT, padx=2, pady=2)
reset_btn = tk.Button(top, text='Reset', command=self._ide_reset)
reset_btn.pack(side=tk.LEFT, padx=2, pady=2)
mid = tk.PanedWindow(frame, orient=tk.HORIZONTAL)
mid.pack(fill=tk.BOTH, expand=True)
self.editor = scrolledtext.ScrolledText(mid)
mid.add(self.editor)
right = tk.Frame(mid)
mid.add(right)
tk.Label(right, text='Input (for ",")').pack(anchor=tk.W)
self.ide_input = tk.Entry(right)
self.ide_input.pack(fill=tk.X, padx=4)
tk.Label(right, text='Output').pack(anchor=tk.W)
self.ide_output = scrolledtext.ScrolledText(right, height=20)
self.ide_output.pack(fill=tk.BOTH, expand=True, padx=4, pady=4)
# Interpreter state for stepping
self._ide_interp = None
def _ide_save(self):
path = filedialog.asksaveasfilename(defaultextension='.morethanzero', filetypes=[('MoreThanZero files', '*.morethanzero'), ('Text files','*.txt'), ('All files','*.*')])
if not path:
return
try:
with open(path,'w', encoding='utf-8') as f:
f.write(self.editor.get('1.0', tk.END))
messagebox.showinfo('Saved', f'Saved to {path}')
except Exception as e:
messagebox.showerror('Error', str(e))
def _ide_load(self):
path = filedialog.askopenfilename(filetypes=[('MoreThanZero files', '*.morethanzero'), ('Text files','*.txt'), ('All files','*.*')])
if not path:
return
try:
with open(path,'r', encoding='utf-8') as f:
txt = f.read()
self.editor.delete('1.0', tk.END)
self.editor.insert(tk.END, txt)
except Exception as e:
messagebox.showerror('Error', str(e))
def _ide_run(self):
code = self.editor.get('1.0', tk.END)
inp = self.ide_input.get()
interp = MoreThanZeroInterpreter(code, input_text=inp)
try:
out = interp.run()
except Exception as e:
out = f'Error: {e}'
self.ide_output.delete('1.0', tk.END)
self.ide_output.insert(tk.END, out)
# reset stepping state
self._ide_interp = None
def _ide_step(self):
if self._ide_interp is None:
code = self.editor.get('1.0', tk.END)
inp = self.ide_input.get()
self._ide_interp = MoreThanZeroInterpreter(code, input_text=inp)
self.ide_output.delete('1.0', tk.END)
try:
cont = self._ide_interp.step()
# append incremental output
self.ide_output.delete('1.0', tk.END)
self.ide_output.insert(tk.END, ''.join(self._ide_interp.output))
if not cont or self._ide_interp.ip >= len(self._ide_interp.code):
self._ide_interp = None
except Exception as e:
messagebox.showerror('Error', str(e))
self._ide_interp = None
def _ide_reset(self):
self._ide_interp = None
self.ide_output.delete('1.0', tk.END)
def _build_file(self, frame):
top = tk.Frame(frame)
top.pack(fill=tk.X)
open_btn = tk.Button(top, text='Open .morethanzero file', command=self._file_open)
open_btn.pack(side=tk.LEFT, padx=4, pady=4)
run_btn = tk.Button(top, text='Run', command=self._file_run)
run_btn.pack(side=tk.LEFT, padx=4, pady=4)
tk.Label(top, text='Input (for ",")').pack(side=tk.LEFT, padx=6)
self.file_input = tk.Entry(top)
self.file_input.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=4)
self.file_code_display = scrolledtext.ScrolledText(frame)
self.file_code_display.pack(fill=tk.BOTH, expand=True)
self.file_code_display.config(state=tk.DISABLED)
bottom = tk.Frame(frame)
bottom.pack(fill=tk.BOTH)
tk.Label(bottom, text='Output').pack(anchor=tk.W)
self.file_output = scrolledtext.ScrolledText(bottom, height=10)
self.file_output.pack(fill=tk.BOTH, expand=True)
self._current_file_path = None
def _file_open(self):
path = filedialog.askopenfilename(filetypes=[('MoreThanZero files','*.morethanzero'), ('Text files','*.txt'), ('All files','*.*')])
if not path:
return
try:
with open(path,'r', encoding='utf-8') as f:
txt = f.read()
self._current_file_path = path
self.file_code_display.config(state=tk.NORMAL)
self.file_code_display.delete('1.0', tk.END)
self.file_code_display.insert(tk.END, txt)
self.file_code_display.config(state=tk.DISABLED)
except Exception as e:
messagebox.showerror('Error', str(e))
def _file_run(self):
if not self._current_file_path:
messagebox.showwarning('No file', 'Open a .morethanzero file first')
return
try:
with open(self._current_file_path,'r', encoding='utf-8') as f:
code = f.read()
except Exception as e:
messagebox.showerror('Error', str(e))
return
inp = self.file_input.get()
interp = MoreThanZeroInterpreter(code, input_text=inp)
try:
out = interp.run()
except Exception as e:
out = f'Error: {e}'
self.file_output.delete('1.0', tk.END)
self.file_output.insert(tk.END, out)
def _build_light(self, frame):
# Minimal UI: small editor, input, run, output. Designed to be tiny.
top = tk.Frame(frame)
top.pack(fill=tk.X)
tk.Label(top, text='Tiny editor (paste code)').pack(side=tk.LEFT)
run_btn = tk.Button(top, text='Run', command=self._light_run)
run_btn.pack(side=tk.RIGHT, padx=4)
self.light_input = tk.Entry(top)
self.light_input.pack(fill=tk.X, padx=4)
self.light_editor = tk.Text(frame, height=8)
self.light_editor.pack(fill=tk.X, padx=4, pady=4)
tk.Label(frame, text='Output').pack(anchor=tk.W)
self.light_output = tk.Text(frame, height=8)
self.light_output.pack(fill=tk.BOTH, expand=True, padx=4, pady=4)
def _light_run(self):
code = self.light_editor.get('1.0', tk.END)
inp = self.light_input.get()
interp = MoreThanZeroInterpreter(code, input_text=inp)
try:
out = interp.run()
except Exception as e:
out = f'Error: {e}'
self.light_output.delete('1.0', tk.END)
self.light_output.insert(tk.END, out)
# ------------------ Small CLI lightweight runner ------------------
# This part is intentionally small and dependency-free. It can be extracted as a separate tiny file named morethanzero_light.py
# For convenience it's included here; run with --cli to use it.
def run_cli_file(path, input_text=''):
try:
with open(path,'r', encoding='utf-8') as f:
code = f.read()
except Exception as e:
print('Error reading file:', e)
return
interp = MoreThanZeroInterpreter(code, input_text=input_text)
try:
out = interp.run()
print(out)
except Exception as e:
print('Runtime error:', e)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='MoreThanZero runner. GUI by default.')
parser.add_argument('--cli', metavar='FILE', help='Run minimal CLI interpreter on FILE and exit')
parser.add_argument('--input', metavar='INPUT', help='Input string for , commands (CLI mode)')
args = parser.parse_args()
if args.cli:
run_cli_file(args.cli, input_text=(args.input or ''))
else:
app = MoreThanZeroGUI()
app.mainloop()
- This interpreter has written by AI
You can create an windows app with this code, because it was written on python+tkinter.
Simple tutorial for using CLI:
python morethanzero_tkinter_and_light.py --cli program.morethanzero --input "..."
Here ... == code
Examples
Output «A»
Without comments
65&
With comments
65 put #6 and #5 to stack & collect #6 and #5 from stack and output them as ASCII character
Output «123»
Without comments
123.
With comments
123 put #1 #2 and #3 to stack . output stack
Output "Hi"
Without comments
72&><105&
