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.

Minimialized Programming Language

From Esolang
Jump to navigation Jump to search

Minimialized Programming Language is designed by PSTF.

It is really minimialized, and I will design the One-character version of it.

Definition

Commands

program     = { statement }
statement   = if_stmt | while_stmt | let_stmt | call_stmt | return_stmt | io_stmt
if_stmt     = "if" expr "then" { statement } [ "else" { statement } ] "end"
while_stmt  = "while" expr "do" { statement } "end"
let_stmt    = "let" ID "=" expr
call_stmt   = "call" ID "(" [ expr { "," expr } ] ")"
return_stmt = "return" expr
io_stmt     = ("print" expr) | ("read" ID) | ("printch" expr) | ("readch" ID)
expr        = term { ("+" | "-" | "==" | "<" | "!=") term }
term        = factor { ("*" | "/") factor }
factor      = INT | CHAR | STRING | ID | "(" expr ")" | ("-" factor) 
            | ID "[" expr "]" | "[" [ expr { "," expr } ] "]"
CHAR        = "'" (any character) "'"
STRING      = '"' (any characters) '"'

Data types

We use integers, booleans, character, and list.

0 represents false, while other values represent true.

Identifier

Any continuous string consisting of lowercase letters, uppercase letters, Arabic numerals, and underscores is a valid identifier, except for the following:

  1. It has the same name as an existing keyword. Solution: Add 'my' in front or slightly modify the format.
  2. Starts with a number. Solution: Add an underscore before the number.

Functions

Functions uniformly use global variables instead of parameters. To be more precise, a function is actually a subroutine.

List Processing

  • append(list, value) will append something to the list.
  • length(list) will return the size of the list.
  • chr(value) will return the corresponding character with the encoding point of value.
  • ord(value) will return the corresponding encoding point of the character value.

Example Programs

Hello, World!

let string = "Hello, World!"
let i = 0
while i < length(string) do
    printch string[i]
end

Fibonacci

read n
call fib
print result
return 0

function fib
  if n < 2 then
    let result = n
    return 0
  else
    let n1 = n - 1
    let n2 = n - 2
    let n = n1
    call fib
    let temp = result
    let n = n2
    call fib
    let result = temp + result
    return 0
  end
end

Intepreter

Python

import sys

class MinilangInterpreter:
    def __init__(self):
        self.vars = {}
        self.functions = {}
        self.output = []
    
    def parse(self, code):
        lines = [line.strip() for line in code.split('\n') if line.strip()]
        functions = {}
        main_code = []
        
        i = 0
        while i < len(lines):
            if lines[i] == 'function':
                func_name = lines[i+1]
                i += 2
                func_body = []
                while i < len(lines) and lines[i] != 'end':
                    func_body.append(lines[i])
                    i += 1
                functions[func_name] = func_body
            else:
                main_code.append(lines[i])
            i += 1
        
        return main_code, functions
    
    def eval_expr(self, expr):
        expr = expr.strip()
        
        # Handle string literals
        if expr.startswith('"') and expr.endswith('"'):
            return list(expr[1:-1])
            
        # Handle character literals
        if expr.startswith("'") and expr.endswith("'") and len(expr) == 3:
            return expr[1]
        
        # Handle list literals
        if expr.startswith('[') and expr.endswith(']'):
            if expr == '[]':
                return []
            elements = expr[1:-1].split(',')
            return [self.eval_expr(elem.strip()) for elem in elements]
        
        # Handle list indexing: var[expr]
        if '[' in expr and expr.endswith(']'):
            var_name, index_expr = expr.split('[', 1)
            index_expr = index_expr[:-1]  # Remove trailing ]
            var_name = var_name.strip()
            index = self.eval_expr(index_expr)
            
            if var_name in self.vars and isinstance(self.vars[var_name], list):
                if isinstance(index, int) and 0 <= index < len(self.vars[var_name]):
                    return self.vars[var_name][index]
            return 0
        
        # Handle built-in functions
        if expr.startswith('length(') and expr.endswith(')'):
            list_expr = expr[7:-1]
            lst = self.eval_expr(list_expr)
            return len(lst) if isinstance(lst, list) else 0
            
        if expr.startswith('chr(') and expr.endswith(')'):
            num_expr = expr[4:-1]
            num = self.eval_expr(num_expr)
            return chr(num) if isinstance(num, int) else ' '
            
        if expr.startswith('ord(') and expr.endswith(')'):
            char_expr = expr[4:-1]
            char = self.eval_expr(char_expr)
            return ord(char) if isinstance(char, str) and len(char) == 1 else 0
        
        # Integer literals
        if expr.isdigit() or (expr[0] == '-' and expr[1:].isdigit()):
            return int(expr)
        
        # Variables
        if expr in self.vars:
            return self.vars[expr]
        
        # Comparisons
        if '==' in expr:
            left, right = expr.split('==', 1)
            return 1 if self.eval_expr(left) == self.eval_expr(right) else 0
            
        if '!=' in expr:
            left, right = expr.split('!=', 1)
            return 1 if self.eval_expr(left) != self.eval_expr(right) else 0
        
        if '<' in expr:
            left, right = expr.split('<', 1)
            return 1 if self.eval_expr(left) < self.eval_expr(right) else 0
        
        # Arithmetic
        if '+' in expr:
            left, right = expr.split('+', 1)
            left_val = self.eval_expr(left)
            right_val = self.eval_expr(right)
            # Handle string concatenation or arithmetic addition
            if isinstance(left_val, str) and isinstance(right_val, str):
                return left_val + right_val
            elif isinstance(left_val, int) and isinstance(right_val, int):
                return left_val + right_val
            else:
                return 0
        
        if '-' in expr and expr.count('-') == 1 and not expr.startswith('-'):
            left, right = expr.split('-', 1)
            return self.eval_expr(left) - self.eval_expr(right)
        
        if '*' in expr:
            left, right = expr.split('*', 1)
            return self.eval_expr(left) * self.eval_expr(right)
        
        if '/' in expr:
            left, right = expr.split('/', 1)
            right_val = self.eval_expr(right)
            return self.eval_expr(left) // right_val if right_val != 0 else 0
        
        # Unary minus
        if expr.startswith('-'):
            return -self.eval_expr(expr[1:])
        
        # Parentheses
        if expr.startswith('(') and expr.endswith(')'):
            return self.eval_expr(expr[1:-1])
        
        return 0
    
    def execute(self, code, is_function=False):
        i = 0
        while i < len(code):
            line = code[i]
            
            if line.startswith('let '):
                # Handle let x = expr and let x[index] = expr
                rest = line[4:].strip()
                if '[' in rest and ']=' in rest:
                    # List assignment: let var[index] = expr
                    var_name, rest = rest.split('[', 1)
                    index_expr, expr = rest.split(']=', 1)
                    var_name = var_name.strip()
                    index = self.eval_expr(index_expr)
                    value = self.eval_expr(expr.strip())
                    
                    if var_name in self.vars and isinstance(self.vars[var_name], list):
                        if isinstance(index, int) and 0 <= index < len(self.vars[var_name]):
                            self.vars[var_name][index] = value
                else:
                    # Regular assignment
                    parts = rest.split('=', 1)
                    var = parts[0].strip()
                    expr = parts[1].strip()
                    self.vars[var] = self.eval_expr(expr)
                
            elif line.startswith('if '):
                # if expr then ... [else ...] end
                cond = line[3:].split('then', 1)[0].strip()
                if self.eval_expr(cond):
                    j = i + 1
                    block = []
                    while j < len(code) and code[j] != 'else' and code[j] != 'end':
                        block.append(code[j])
                        j += 1
                    self.execute(block, is_function)
                    while j < len(code) and code[j] != 'end':
                        j += 1
                    i = j
                else:
                    j = i + 1
                    while j < len(code) and code[j] != 'else':
                        j += 1
                    if j < len(code) and code[j] == 'else':
                        j += 1
                        block = []
                        while j < len(code) and code[j] != 'end':
                            block.append(code[j])
                            j += 1
                        self.execute(block, is_function)
                    i = j
                    
            elif line.startswith('while '):
                # while expr do ... end
                cond = line[6:].split('do', 1)[0].strip()
                j = i + 1
                block = []
                while j < len(code) and code[j] != 'end':
                    block.append(code[j])
                    j += 1
                
                while self.eval_expr(cond):
                    self.execute(block.copy(), is_function)
                i = j
                
            elif line.startswith('call '):
                # call function or built-in
                rest = line[5:].strip()
                if rest.startswith('append(') and rest.endswith(')'):
                    # Built-in append function
                    args = rest[7:-1].split(',', 1)
                    if len(args) == 2:
                        list_expr = args[0].strip()
                        value_expr = args[1].strip()
                        lst = self.eval_expr(list_expr)
                        value = self.eval_expr(value_expr)
                        if isinstance(lst, list):
                            lst.append(value)
                else:
                    # User-defined function
                    func_name = rest.split('(')[0].strip()
                    if func_name in self.functions:
                        self.execute(self.functions[func_name].copy(), True)
                    
            elif line.startswith('return '):
                expr = line[7:].strip()
                return self.eval_expr(expr)
                
            elif line.startswith('print '):
                expr = line[6:].strip()
                value = self.eval_expr(expr)
                if isinstance(value, list):
                    # Print list as string
                    self.output.append(''.join(str(c) for c in value))
                else:
                    self.output.append(str(value))
                    
            elif line.startswith('printch '):
                expr = line[8:].strip()
                value = self.eval_expr(expr)
                if isinstance(value, str) and len(value) == 1:
                    self.output.append(value)
                elif isinstance(value, int):
                    self.output.append(chr(value))
                else:
                    self.output.append('?')
                    
            elif line.startswith('read '):
                var = line[5:].strip()
                try:
                    value = int(input())
                    self.vars[var] = value
                except:
                    self.vars[var] = 0
                    
            elif line.startswith('readch '):
                var = line[7:].strip()
                try:
                    char = input()[0]  # Get first character
                    self.vars[var] = char
                except:
                    self.vars[var] = ' '
                    
            i += 1
        
        return 0
    
    def run(self, code):
        main_code, self.functions = self.parse(code)
        self.execute(main_code)
        return ''.join(self.output)

# Example usage and tests
if __name__ == "__main__":
    interpreter = MinilangInterpreter()
    
    # Test string reversal
    reverse_code = """
    let text = "hello"
    let reversed = []
    let i = length(text) - 1

    while i >= 0 do
      call append(reversed, text[i])
      let i = i - 1
    end

    let i = 0
    while i < length(reversed) do
      printch reversed[i]
      let i = i + 1
    end
    """
    
    print("String reversal test:")
    print(interpreter.run(reverse_code))
    print()
    
    # Test list operations
    list_code = """
    let numbers = [1, 2, 3, 4, 5]
    let sum = 0
    let i = 0

    while i < length(numbers) do
      let sum = sum + numbers[i]
      let i = i + 1
    end

    print "Sum: "
    print sum
    """
    
    print("List sum test:")
    interpreter2 = MinilangInterpreter()
    print(interpreter2.run(list_code))

Categories