We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

MoreThanZero

From Esolang
(Redirected from MTZ)
Jump to navigation Jump to search
MoreThanZero
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&

upload as .morethanzero