(怒)自制编程语言

  对于这方面的资料,我实在是看不下去了,真是让人非亲自动手不可。上场yacc和lex,满口os和汇编,这让人怎么搞?

  造轮子?对。虽然砌砖才是该干的事——下面开始。


要做些什么?

  目的之一是可以自行添加特性,之二是对匹配方法很反感,另外我一直相信能用谁都看得懂的方法做出大事。至于我为什么这么想……是因为我在接触python前还接触过另一门语言——scheme——这可能导致了我奇怪的思维方式,比如“算术表达式怎么能一下子列完呢?”虽然我没有用scheme写过任何东西,更看不惯那么多括号。

  不妨先定个目标——【用此语言实现helloworld】【用此语言实现fizzbuzz】,demo先行。

  helloworld是很简单的,比如python只要

print("Hello,world!")

  但是还可以这样(cmd脚本):

@echo Hello, world!

  不过C该作为标准:

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
}

  我选择使用如下形式,并给这种语言起名error#1:

(print "Hello world!")

  下面开始实现——慢着,实现?怎么实现?我的64位机想汇编真的是……网上说学X64得先学16和32,而……那么只好用C了,但是我正是反感C中的输入输出流……算了,重写一个操作系统吧,用C写一份,再用汇编写一份装虚拟机,不过逻辑肯定是先用python写。简直是比功能减少的自举还夸张……不过不要紧,我们先用python实现,并调用python模拟的操作系统好了……

  另附初代全家福一张(0KB瞩目)
(怒)自制编程语言

(2018-1-15 于地球)(待续)

https://github.com/lamdba/error_s1

(2018-1-16 于地球)(待续)

。。。。。。

(2018-1-19 于地球)(待续)

  我希望我的语言能像scheme一样。但是我最近遇到了一个问题,那就是scheme里没有字面表。(或许只是我不记得了?)如果要像py一样表示 [1,2,3,4],scheme中似乎应当使用 (1 2 3 4) ,(注:真正的scheme可以用(cons 1 (cons 2 (cons 3 (cons 4 ())))),这显然很冗长)然而解释器看到这个表,自然会把1当做函数,234当成参数来求值。我既然是自己设计语言,自然可以发明新语法,比如用[1 2 3 4]来表示。问题在于,假如表的元素是表达式,比如[(+ 1 1) (+ 2 1) (+ 3 1) (+ 4 1)] ,那么这里边的表达式,该不该算呢?——“显然是应该计算的”——于是,我们无论如何都不能够把一个函数的代码放进一个表了,而我本希望把函数用一个表代替,并且这个表最好和它定义的时候一样,比如 ([[a b] (/ (+ a b) 2)] 4 6) ,它理应表示“定义一个平均函数,然后作用于4和6”。在scheme里,有define函数来做这个,但define令人困惑,不仅它改变了环境(函数式编程不可以改变变量,但可以创建新的),而且它显然没有对子表达式求值。

  我于是想反悔之前的“显然”了,不过我刚才似乎又引入了一个“显然”:函数“应当”是一个表。如果我们不对表之内的东西求值,那么就可以把这个函数的表达式部分装进一个表里了。(附:这些我想了两天,仍旧无法表述清楚,我说的一切都不很明确)但是对于某些表,比如之前的[(+ 1 1) (+ 2 1) (+ 3 1) (+ 4 1)],我们又想把它求值。虽然我也想到,不求值并没有关系,但……有没有办法控制哪些求值呢?如果一个函数能接收参数,其中有些要作为值传入,有些要作为表达式传入……

  即使是一个表,也可以强制看成表达式求值。但是表中若还有表,这些如何说呢?如果一个表不能影响其子表达式的求值方式,那么这个语言永远不可能原封不动地把表达式当成数据。(我其实是想说,如果要求定义函数时添加额外信息,也许就能解决),但我还有另一个解决方案:函数有不处理表达式的权利。这样,define就情有可原了,甚至不需要方括号了,不处理表达式的函数是lazy(“惰性”)的,但似乎得对每一个参数定义是否惰性……而定义参数惰性与否,又让人心想能不能在传入时才定义其惰性。定义函数如此,那么定义表呢?连定义一个表都得逐个区分惰性与否。比如[define f [[lazy a][not-lazy b]] (cons a b)] (即使我不想让define改变环境,我也可以用环境字典的方法处理), [set l [(+ 1 2) (+ 1 2)]] ……如果我非要让前一个(+ 1 2)求值,后一个不求值,我得做啥呢?——[set l [not-lazy lazy] [(+ 1 2) (+ 1 2)]],一个表要每时每刻都背负lazy与否的信息。而显然还有另一种写法,用[lazy (+ 1 2)]这种序对组成的表表示。一个表达式是否被求值,其本身是无法做决定的,只能把这个问题抛给上一层,不管是表还是表达式。

  另外我不希望函数的参数数量是可变的,除非一切函数都必须把参数打包,这虽然可能,但不漂亮……

  表的lazy与否设定起来及其累赘,但为了结构上的美感,这是应当的。(但默认not-lazy似乎是必须的)此外,把“lazy与否”和参数打包,好看且可以对齐,但似乎会出问题……不妨试试:(允许参数lazy设定,则不求值表达式可以当做表!)

(set-lazy l (lazy not-lazy) ((+ 1 2) (+ 1 2)))    # set 的后2个参数都是lazy的   

  (虽然我也不喜欢set,但也可以添加一个环境参数使其成为纯粹函数)

  但是(依旧是模糊地),会不会出现一个函数,在not-lazy位上接收到了lazy表达式呢?我们刚才说的,好像都仅限于字面求值。 (更可怕的是,我连符号代换都没有实现,固然语言可以实现自己,函数之间可以互相实现,初始实现还是要的)其实(似乎)表达式本身是不存在lazy与否的,lazy仅仅是对子式的概念。所以不会有这种矛盾。(退一步想,我这种问题,如果是追求严谨的教程,恰恰无法把它写上去,可理应有人困惑啊)

  但是,其实表达式本身lazy与否,也是有的,这正是 () 和 [] 的差异。它们都可以有lazy的子式或not-lazy的子式,但它们对自己一个求值,一个不求值。这二者应当可以互相转换,但能否统一呢?能否用(lazy (1 2 3 4)) (lazy的参数定义为lazy的)来表示[1 2 3 4] 呢?应该是可以的。不过这虽然省下一个符号,却没有把表这个类(笑)也省了。一个not-lazy 的参数位,收到一个表,对这个表求值永远是可以的(虽然未必合法),把它当成一个整体也永远是可以的,所以按理必须有二者之别。

  我昨晚想到了穿透求值和非穿透求值,但仅仅分了4类,没有想到区分每个参数是否lazy。不过到这里仅仅是“给人豁然开朗”的感觉,实际的替换又会带来一系列问题。今天就先写到这里罢。

  如有谁能看到这里,我很佩服。

(2018-5-17 于地球)

  目前已经支持递归

(2018-6-5 于地球)

  基于python函数调用的实现只能维持1000层调用。error2用栈实现,可以支持更多的调用。但是其中还有许多函数没有实现,包括基本的cons,car,cdr等等。但既然大功告成,我此时还有别的事要做,这些等以后再说罢,可以在为其他事抓狂时,有他事可做……

(2018-6-14 于地球)

转载于:https://blog.51cto.com/13535617/2061128

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值