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.

Prime

From Esolang
Jump to navigation Jump to search

Prime 语言由 Fictology 设计,最初的设想来自于 算术基本定理 。其核心思想是将栈操作指令、数据类型、lambda演算等统统看作独特的类型,这些不同的类型用不同的质数进行表示,如果想要添加组合类型直接将这些质数相乘,根据算术基本定理,相乘的结果也必定是唯一的合数,从而达到“类型即程序”的设计美感。 Prime 语法仅由数字和分隔符组成(本文中使用英文逗号作为分隔符),其它所有符号都被编译器忽略,数字和逗号交替出现构成一个列表,其中,列表偶数索引的位置是类型信息,奇数索引的位置是数据信息。它们共同构成一个二元组,Prime 语言中一切皆由这个二元组所组成。

Command Table

1.0版本的操作指令
质数 名称 含义 数据字段用途
2 PUSH 将数据压入栈 要压入的整数
3 POP 弹出栈顶 忽略
5 COMPOSE 态射/顺序标记(NOP) 忽略
7 DUP 复制栈顶 忽略
13 OUT 弹出栈顶,作为 ASCII 字符输出 忽略
17 IN 读取一个 ASCII 字符,将其码值压栈 忽略
19 JZ 弹出栈顶,若为 0 则跳转 跳转目标索引
21 JMP 无条件跳转 跳转目标索引

Example

119,0,19,4,13,0,23,0,0,0

(没错,这真的就是 Prime 语言的样子。这里实现了一个简单的读取输入返回输出的 Prime 程序)

Prime Language Compiler

import re
from sympy import factorint

# 基类型定义
PRIMES = {
    2: 'PUSH', 3: 'POP', 5: 'COMPOSE', 7: 'DUP',
    13: 'OUT', 17: 'IN', 19: 'JZ', 23: 'JMP'
}

def parse(src):
    """词法:只提取数字,其他全忽略;0-based 偶数为类型,奇数为数据"""
    toks = [int(x) for x in re.findall(r'\d+', src)]
    if len(toks) % 2:
        toks.append(0)
    return [(toks[i], toks[i+1]) for i in range(0, len(toks), 2)]

def run(pairs):
    stack = []
    i = 0
    while i < len(pairs):
        ty, dat = pairs[i]
        if ty == 0:          # NEVER: 停止执行
            break
        if ty == 1:          # ANY: 跳过
            i += 1
            continue
        
        # 分解类型合数
        factors = factorint(ty)
        # 按质数顺序执行(体现类型组合)
        for p in sorted(factors):
            op = PRIMES.get(p)
            if op == 'PUSH':
                stack.append(dat)
            elif op == 'POP':
                if stack: stack.pop()
            elif op == 'DUP':
                if stack: stack.append(stack[-1])
            elif op == 'OUT':
                if stack: print(chr(stack.pop()), end='', flush=True)
            elif op == 'IN':
                try:
                    ch = input()[0]
                    stack.append(ord(ch))
                except (EOFError, IndexError):
                    stack.append(0)
            elif op == 'JZ':
                if stack and stack.pop() == 0:
                    i = dat   # 跳转
                    break
            elif op == 'JMP':
                i = dat      # 跳转
                break
            # COMPOSE(5) 等其它类型在此扩展
        else:
            i += 1  # 如果没有跳转,继续下一条
            continue
        if ty in (19, 23):  # 如果执行了跳转,已经在上面设了 i,这里不再 +1
            continue