Simple,是一种解释型的Esolang语言,特色是极度简单的语法、功能和机制,也支持一部分Python语法,由Pinpe在2024年初秋因为洗澡时的灵光一现而开始开发,作为一门贯彻极简主义的语言,同时还保留一定的可读性。除了四大核心语句,其它一切语句都是API,而且拒绝“无关紧要”的抽象概念,例如循环、数据结构、函数、对象、模块,甚至注释,因此编写Simple程序非常繁琐且需要抽象思维。
解释器自带了一个简单的编辑器,因此可以直接在终端上编辑代码,而且支持交互和脚本两种模式。
要声明一个全局变量(也只有全局变量),只需要给出变量名和值,中间用:核心语句分隔:
hello: ‘hi, mom’
用putAPI可以打印到标准输出:
hello: ‘hi, mom’ put hello
用keyAPI可以获取键盘输入,其参数就是想要把结果传递到的变量:
put ‘who: ’ key name hello: ‘hi, ’ + name put hello
这就是你的第一个Simple程序,但实际上此时事情还没有开始奇怪起来。
数据类型
Simple有完整且简单的数据类型系统:
符号意义示例num数字(包含整数和浮点数)3、3.14str字符串(要用”或""包围)‘hello’bool布尔值(只有True和Flase)True、FlaseNone空值Noneother除上面所述的其它类型(非标准)[‘list’]、<object>
核心语句
核心语句每一样都不可缺少,否则就无法构成图灵完备,就像大脑一样,只需用符号表示。
:
{变量名}: {变量值}
声明一个变量,例如:
var: ‘hello’
如果使用了未声明的变量,将返回None。
::
:: {标签名}
声明一个标签,需要和下文的->搭配使用,实际上是语法糖,原形为:
{标签名}: {声明此标签时的行号}
示例:
:: my_label
->
{条件表达式(可选,默认为True)} -> {跳转到的行号}
当满足条件表达式里的条件时,指针就会跳转到相应的行号,这是唯一可以控制代码流程的语句,例如:
sum == 90 -> 8
最好和标签搭配使用,当代码行数变动时就不会波及到->:
sum == 90 -> great
@
@ {想要执行的代码字符串}
动态执行字符串里的代码,例如:
var: ‘hello’ @ “put ’” + var + ”‘“
API
API也是很重要的,没有API就无法进行实际操作,就像手一样,用简短单词标识。
由于API比较多,就不详细展开了,稍微讲一下每个API的用途,详细请看源代码:
**sh、py:**分别调用系统Shell和Python解释器。
**put、key:**输出和输入。
**num、str、type:**前两个是转换到某种类型,后一个是检查类型。
**len:**返回字符串的长度。
**file、write:**文件操作。
**sleep:**时间延迟。
**tur_down、tur_up、tur_done、tur_to、tur_size、tur_color:**海龟画图。
部分抽象概念的实现
注释
可使用变量代替:
rem: ‘这是一个注释’
条件循环(也可以通过@升级为遍历)
var: 0 :: root var: var + 1 put var var != 5 -> root
示例代码
put ‘a = ’ key a num a put ‘b = ’ key b num b
a > b -> big a < b -> less put ‘两者相等\n’ -> quit
:: big put ‘a比b大\n’ -> quit
:: less put ‘a比b小\n’ -> quit
:: quit
解释器源码
import os import time import turtle
def clean(): print(‘\033[2J’) print(‘\033[H’, end=”)
def interpreter(pointer): try: if not pointer: pass elif ‘sh’ in pointer: pretreatment = pointer.replace(‘sh’,”).strip() exec(f’os.system({pretreatment})’, globals()) elif ‘py’ in pointer: pretreatment = pointer.replace(‘py’,”).strip() exec(pretreatment, globals()) elif ’@’ in pointer: pretreatment = pointer.replace(’@’,”).strip() interpreter(eval(pretreatment, globals())) elif ‘put’ in pointer: pretreatment = pointer.replace(‘put’,”) print(eval(pretreatment, globals()), end=”, flush=False) elif ‘write’ in pointer: pointer = pointer.strip(‘write’) parts = [p.strip() for p in pointer.split(’,’)] name, content = parts[0], parts[1] exec(f”{name}.write({content})”, globals()) elif ’:’ in pointer and not ’::’ in pointer: pretreatment = pointer.split(’:’) name = pretreatment[0] key = pretreatment[1] exec(f’{name} = {key}’, globals()) elif ’->’ in pointer: pretreatment = pointer.split(’->’) condition = pretreatment[0].strip() target_line = eval(pretreatment[1], globals()) - 1 if not condition or eval(condition, globals()): return target_line elif ‘key’ in pointer: pretreatment = pointer.replace(‘key’,”).strip() exec(f’{pretreatment} = input()’, globals()) elif ‘num’ in pointer: pretreatment = pointer.replace(‘num’,”).strip() try: exec(f’{pretreatment} = int({pretreatment})’, globals()) except Exception: exec(f’{pretreatment} = float({pretreatment})’, globals()) elif ‘str’ in pointer: pretreatment = pointer.replace(‘str’,”).strip() exec(f’{pretreatment} = str({pretreatment})’, globals()) elif ‘type’ in pointer: pretreatment = pointer.replace(‘type’,”).strip() global results if isinstance(eval(pretreatment), int) or isinstance(eval(pretreatment), float): results = ‘num’ elif isinstance(eval(pretreatment), str): results = ‘str’ else: results = ‘other’ exec(f’{pretreatment} = results’, globals()) elif ‘len’ in pointer: pretreatment = pointer.replace(‘len’,”).strip() exec(f’{pretreatment} = len({pretreatment})’, globals()) elif ‘sleep’ in pointer: pretreatment = pointer.replace(‘sleep’,”).strip() pretreatment = eval(pretreatment) time.sleep(pretreatment) elif ‘file’ in pointer: pretreatment = pointer.replace(‘file’, ”).strip() parts = [p.strip() for p in pretreatment.split(’,’)] name, path, mode, encoding = parts exec(f”{name} = open({path}, {mode}, encoding={encoding})”, globals()) elif ‘tur_down’ == pointer: turtle.pendown() elif ‘tur_up’ == pointer: turtle.penup() elif ‘tur_done’ == pointer: turtle.done() elif ‘tur_to’ in pointer: pointer = pointer.strip(‘tur_to’) parts = [p.strip() for p in pointer.split(’,’)] x, y = parts[0], parts[1] exec(f’turtle.goto({x}, {y})’, globals()) elif ‘tur_size’ in pointer: pretreatment = pointer.replace(‘tur_size’,”).strip() pretreatment = eval(pretreatment, globals()) turtle.pensize(pretreatment) elif ‘tur_color’ in pointer: pretreatment = pointer.replace(‘tur_color’,”).strip() pretreatment = eval(pretreatment, globals()) turtle.pencolor(pretreatment) elif ’::’ in pointer: pass else: raise SyntaxError(“invalid syntax”) except NameError as err_obj: err_str = str(err_obj).replace(‘name’, ”).replace(‘is not defined’, ”).replace(”’”, ”).strip() exec(f’{err_str} = None’, globals()) interpreter(pointer) return line + 1
def main(): '''标签预处理''' global line line = 0 while line < len(all_code): pointer = all_code[line] if ’::’ in pointer: pretreatment = pointer.replace(’::’,”).strip() exec(f’{pretreatment} = {line + 1}’, globals()) line += 1
'''解释器'''
line = 0
while line < len(all_code):
pointer = all_code[line].strip()
new_line = interpreter(pointer)
line = new_line
'''编辑器''' if name == ‘main’: all_code = [] show_line = 1 clean() print(‘\033[1m\033[34m欢迎使用由Pinpe制作的Simple语言\033[m,此语言力求最极简的语法和机制,当前版本为\033[1m\033[33mb0.3\033[m。\n编辑器的当前模式是\033[1m\033[33m交互\033[m,可以使用\033[4m\033[31m回车键\033[m直接执行一行程序,\033[1m\033[31m不支持->等部分功能\033[m,输入\033[4m\033[31mscript\033[m进入脚本模式,输入\033[4m\033[31mexit\033[m退出。’) while True: keyboard = input(‘\n\033[1m\033[33m输入\033[m\033[34m >> \033[m’) if keyboard == ‘script’: clean() print(‘编辑器的当前模式是\033[1m\033[33m脚本\033[m,可以使用\033[4m\033[31mrun\033[m执行多行程序,输入\033[4m\033[31mshell\033[m进入交互模式。\n’) while True: keyboard = input(f’\033[1m\033[33m{show_line}\033[m\033[34m | \033[m’) if keyboard == ‘run’: clean() main() exit(0) elif keyboard == ‘shell’: show_line = 1 clean() print(‘\033[1m\033[34m欢迎使用由Pinpe制作的Simple语言\033[m,此语言力求最极简的语法和机制,当前版本为\033[1m\033[33mb0.3\033[m。\n编辑器的当前模式是\033[1m\033[33m交互\033[m,可以使用\033[4m\033[31m回车键\033[m直接执行一行程序,\033[1m\033[31m不支持->等部分功能\033[m,输入\033[4m\033[31mscript\033[m进入脚本模式,输入\033[4m\033[31mexit\033[m退出。’) break else: all_code.append(keyboard) show_line += 1 elif keyboard == ‘exit’: exit(0) else: all_code.append(keyboard) main() all_code = []