Minimialized Programming Language 2

From Esolang
Jump to navigation Jump to search

Minimialized Programming Language 2 is the Single Character version of Minimialized Programming Language.

Definition

Commands

=   let (assignment)
?   print
?c  print character
$   read integer  
$c  read character
(   if
)   then/else separator  
{   while
}   end block
[   list literal
]   list index
@   function call
!   return
,   argument separator
+   add
-   subtract
*   multiply
/   divide
<   less than
>   greater than
&   and
|   or
~   not

Others are same as MPL.

Examples

String Reversal

=t"hello"
=r[
=i-t~0
{i>i0)
  @a r,t i
  =i-i1
}
=i0
{i< i~r)
  ?c r i
  =i+i1
}

Interpreter

import sys

class HexagonInterpreter:
    def __init__(self):
        self.vars = {}
        self.funcs = {}
        self.output = []
        self.stack = []
    
    def parse(self, code):
        lines = [line.strip() for line in code.split('\n') if line.strip()]
        main = []
        current_func = None
        
        for line in lines:
            if not line: continue
            
            if line[0].isalpha() and len(line) == 1:
                # Function definition: f( ... }
                current_func = line[0]
                self.funcs[current_func] = []
            elif current_func is not None:
                if line == '}':
                    current_func = None
                else:
                    self.funcs[current_func].append(line)
            else:
                main.append(line)
        
        return main
    
    def eval_expr(self, expr):
        expr = expr.strip()
        if not expr: return 0
        
        # Handle numbers
        if expr.isdigit() or (expr[0] == '-' and expr[1:].isdigit()):
            return int(expr)
        
        # Handle variables
        if expr in self.vars:
            return self.vars[expr]
        
        # Handle string literals
        if expr.startswith('"') and expr.endswith('"'):
            return list(expr[1:-1])
        
        # Handle list literals
        if expr.startswith('[') and expr.endswith(']'):
            if expr == '[]': return []
            elements = expr[1:-1].split(',')
            return [self.eval_expr(e.strip()) for e in elements if e.strip()]
        
        # Handle list indexing: var[expr]
        if '[' in expr and expr.endswith(']'):
            var, idx_expr = expr.split('[', 1)
            idx_expr = idx_expr[:-1]
            var = var.strip()
            idx = self.eval_expr(idx_expr)
            if var in self.vars and isinstance(self.vars[var], list):
                if 0 <= idx < len(self.vars[var]):
                    return self.vars[var][idx]
            return 0
        
        # Handle built-in functions in expressions
        if expr.startswith('~'):  # Length
            val = self.eval_expr(expr[1:])
            return len(val) if isinstance(val, list) else 0
        
        # Handle comparisons and arithmetic
        for op in ['==', '!=', '<', '>', '<=', '>=', '+', '-', '*', '/']:
            if op in expr:
                left, right = expr.split(op, 1)
                lval = self.eval_expr(left)
                rval = self.eval_expr(right)
                
                if op == '==': return 1 if lval == rval else 0
                if op == '!=': return 1 if lval != rval else 0
                if op == '<': return 1 if lval < rval else 0
                if op == '>': return 1 if lval > rval else 0
                if op == '<=': return 1 if lval <= rval else 0
                if op == '>=': return 1 if lval >= rval else 0
                if op == '+': return lval + rval
                if op == '-': return lval - rval
                if op == '*': return lval * rval
                if op == '/': return lval // rval if rval != 0 else 0
        
        return 0
    
    def execute_line(self, line):
        if not line: return None
        
        cmd = line[0]
        rest = line[1:].strip()
        
        if cmd == '=':  # Assignment
            if '[' in rest and ']=' in rest:
                # List assignment: var[idx]=expr
                var, rest = rest.split('[', 1)
                idx_expr, expr = rest.split(']=', 1)
                var = var.strip()
                idx = self.eval_expr(idx_expr)
                val = self.eval_expr(expr)
                if var in self.vars and isinstance(self.vars[var], list):
                    if 0 <= idx < len(self.vars[var]):
                        self.vars[var][idx] = val
            else:
                # Regular assignment: var=expr
                if '=' in rest:
                    var, expr = rest.split('=', 1)
                    self.vars[var.strip()] = self.eval_expr(expr)
        
        elif cmd == '?':  # Print
            if rest.startswith('c '):  # Print character
                val = self.eval_expr(rest[2:])
                if isinstance(val, str):
                    self.output.append(val)
                elif isinstance(val, int):
                    self.output.append(chr(val))
            else:  # Print normal
                val = self.eval_expr(rest)
                if isinstance(val, list):
                    self.output.append(''.join(str(x) for x in val))
                else:
                    self.output.append(str(val))
        
        elif cmd == '$':  # Read
            if rest.startswith('c '):  # Read character
                var = rest[2:].strip()
                try:
                    ch = input()[0]
                    self.vars[var] = ch
                except:
                    self.vars[var] = ' '
            else:  # Read integer
                var = rest.strip()
                try:
                    self.vars[var] = int(input())
                except:
                    self.vars[var] = 0
        
        elif cmd == '(':  # If
            cond = self.eval_expr(rest)
            return ('if', cond)
        
        elif cmd == ')':  # Then/Else separator
            return ('else',)
        
        elif cmd == '{':  # While
            cond = self.eval_expr(rest)
            return ('while', cond)
        
        elif cmd == '}':  # End block
            return ('end',)
        
        elif cmd == '@':  # Function call
            func = rest.strip()
            if func in self.funcs:
                # Save state for return
                self.stack.append(self.vars.copy())
                result = self.execute_block(self.funcs[func])
                self.vars = self.stack.pop()
                return result
        
        elif cmd == '!':  # Return
            val = self.eval_expr(rest)
            return ('return', val)
        
        return None
    
    def execute_block(self, block):
        i = 0
        while i < len(block):
            line = block[i]
            result = self.execute_line(line)
            
            if result and result[0] == 'if':
                _, cond = result
                if cond:
                    # Execute then block
                    then_block = []
                    i += 1
                    while i < len(block) and block[i] != ')':
                        then_block.append(block[i])
                        i += 1
                    ret = self.execute_block(then_block)
                    if ret and ret[0] == 'return':
                        return ret
                    # Skip else block if present
                    if i < len(block) and block[i] == ')':
                        i += 1
                        while i < len(block) and block[i] != '}':
                            i += 1
                else:
                    # Skip then block, find else
                    i += 1
                    while i < len(block) and block[i] != ')':
                        i += 1
                    if i < len(block) and block[i] == ')':
                        i += 1
                        # Execute else block
                        else_block = []
                        while i < len(block) and block[i] != '}':
                            else_block.append(block[i])
                            i += 1
                        ret = self.execute_block(else_block)
                        if ret and ret[0] == 'return':
                            return ret
            
            elif result and result[0] == 'while':
                _, cond = result
                while_block = []
                i += 1
                while i < len(block) and block[i] != '}':
                    while_block.append(block[i])
                    i += 1
                while cond:
                    ret = self.execute_block(while_block.copy())
                    if ret and ret[0] == 'return':
                        return ret
                    cond = self.eval_expr(block[0][1:])  # Re-evaluate condition
            
            elif result and result[0] == 'return':
                return result
            
            i += 1
        return None
    
    def run(self, code):
        main_code = self.parse(code)
        self.execute_block(main_code)
        return ''.join(self.output)

# Ultra-compact test cases
if __name__ == "__main__":
    hexagon = HexagonInterpreter()
    
    # Factorial in golfed syntax
    factorial_code = """
=n5
=r1
@f
?r

f(
  =n0)
  !1
  )
  =tn
  =n-n1
  @f
  =r*t r
  !0
}
"""
    
    print("Factorial of 5:")
    print(hexagon.run(factorial_code))
    
    # String reversal
    hexagon2 = HexagonInterpreter()
    reverse_code = """
=t"hello"
=r[
=i-~t0
{i>i0)
  @a r,t i
  =i-i1
}
=i0
{i< i~r)
  ?c r i
  =i+i1
}

a(
  =l~0
  =0 l]v
  =l+ l1
  !0
)
"""
    print("\nString reversal:")
    print(hexagon2.run(reverse_code))

Categories