MoreThanZero
Jump to navigation
Jump to search
- 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&