系列文章目录
TON(五)
TON(四)
TON(三)
TON(二)
TON(一)
前言
fift是一门十分强大的栈编程语言,,在TON中它是由c++编译而成的语言,可自身依然具有很高的拓展性。接下来为大家演示几个有趣的算法,今天先来改个注释玩玩。
一、fift注释的严格格式
在fift语言中,经常会遇到一个奇怪的现象就是使用注释// 必须要空一格才会有效果?
// 这是一个注释
使用这种方法输入的文本会正常通过编译,而如果解接下来的这种情况
//这是一个注释
就会抛出错误
└─$ toncli fift run '/home/zqy/tonlearn/v.fif'
[ 1][t 0][2024-10-14 01:08:49.172379300][Fift.cpp:66] top: <continuation 0x2351160>
level 1: <continuation 0x2347ca0>
level 2: <text interpreter continuation>
[ 1][t 0][2024-10-14 01:08:49.172399715][fift-main.cpp:192] Error interpreting file `/home/zqy/tonlearn/v.fif`: v.fif:1: //这是一个注释:-?
在 Fift 语言中,注释的使用需要遵循特定的语法规则。Fift 语言的注释通常以 // 开头,后面紧跟着至少一个空格,然后是注释文本。如果 // 后面直接紧跟着注释文本而没有空格,Fift 解释器可能会将其解释为代码的一部分,从而导致编译错误。
我们来仔细思考一下,如果是C++ 支持两种类型的注释:
-
单行注释:使用
//
开头,后面紧跟注释文本。这与 Fift 中的单行注释类似,但通常不需要空格。//这是一个单行注释
-
多行注释:使用
/*
开头,以*/
结尾。这种注释可以跨越多行。/* 这是一个 多行注释 */
会发现自由的多,那么我们是否可以通过元语的拓展来将fift具备更加灵活的注释呢?
二 fift注释的底层逻辑
活动词和普通词
首先先让我们来探究一下注释的源代码:
{ 0 word drop 0 'nop } :: //
这是标准库的第一条源代码,也就是说,fift本身是没有任何注释的方式的,必须从标准库中才可以找到相关的定义。
在 Fift 语言的世界里,有一个叫做 state 的神秘变量,它就像一个幕后英雄,控制着解释器的行为。这个 state 变量是内部的,我们这些编程的人通常触碰不到它。它的作用很简单,但影响巨大:当 state 为零时,解释器就像一个急性子,遇到任何词素都会立刻查字典并执行。但如果 state 为正数,解释器就会变得冷静,它会把找到的词素记下来,但不马上执行,而是把它们加入到一个正在构建的代码列表中。
这个 state 变量通常代表了当前打开的代码块的数量。比如,如果你写了 { 0= { .“zero”,这就像是打开了两扇门,state 就变为了二。这时,你正在构建的代码列表就放在堆栈的最上面。
当你写下 {,就像是对解释器说:“嘿,我要开始一个新的代码块了。”这时,一个新的空列表就会出现在堆栈上,state 也会增加一。而当你写下 },就像是说:“我完成这个代码块了。”如果 state 不是零,它就会减少一,并且把完成的代码块留在堆栈上。如果 state 还不是零,这个新的代码块就会被当作一个匿名的常量,编译到更大的代码块中。
在 Fift 中,还有一种特别的词素,叫做活动词素(active words)。这些词素不像普通的词素那样乖乖地听从 state 的指挥。无论 state 是什么,活动词素总是被执行。它们在堆栈上留下一些值和执行令牌,然后解释器会根据 state 的值来决定下一步怎么做。如果 state 是零,它就会忽略那些值,只执行那个执行令牌。如果 state 不是零,它就会把那些值和执行令牌编译到当前的代码列表中。
而根据上面的 ::
这个代码的出现,实际上是定义了一个 Fift 活动词,active words,也就是//
word 命令
在 Fift 语言中,word
是一个强大的命令,它能够识别并捕获字符串。当 word
与 {}
结合使用时,它能够从特定的代码块中提取字符串。这个过程涉及到对代码文本的解析和处理,非常类似于魔法师在施展咒语时,能够从周围的空气中提取出无形的元素。
-
识别字符串:
word
它从}
后面的第一个空格之后开始识别内容,直到遇到由word
前面的词素定义的中断点。这个中断点可以是任何字符或字符序列,它告诉word
在哪里停止捕获字符串。 -
捕获为字符串:一旦
word
识别了要捕获的文本,它就会将这段文本作为一个字符串压入堆栈。这意味着这段文本现在可以被 Fift 程序作为数据进行处理,比如打印输出、存储或作为其他操作的参数。 -
中断点的定义:
word
原语前面的词素定义了捕获字符串的中断点。例如,如果使用char * word
,那么*
就是中断点。这意味着word
会捕获从{}
后面的第一个空格开始,直到遇到*
之前的所有文本。
如下面的一个例子:
{ char * word } 我的小猫咪 // 么么 * 哈哈哈
在这个例子中:
char *
定义了捕获字符串的中断点为*
字符。word
开始捕获从{}
后面的第一个空格之后的所有文本,直到遇到*
。我的小猫咪 // 么么
被识别为一个字符串,并压入堆栈。哈哈哈
是*
之后的文本,不会被包含在捕获的字符串中。
这个过程非常强大,因为它允许 Fift 程序动态地识别和处理文本,就像魔法师能够从周围的世界中提取和操纵无形的元素一样。
所以在我们的原始定义中0 word
就表示不需要任何中断,也就是所有的}
空格之后的内容都会被变为字符串。
丢弃与毫无意义的操作
drop 0 'nop
是word 之后的操作,它表示将栈顶部的一个元素丢弃,然后移除0 在进行无意义的操作,啥也不做。
这真的很low,啥也不做放到这里有啥用????
三 美化注释行动
丢掉垃圾
首先,我一定要把,0 'nop
删除,拉黑,碍眼睛,占地放。具体的方式就是,用普通词重新写他:
{ 0 word drop } : //
我们用:
定义,普通词不需要特定的后续令牌操作,那些也没必要,将更改后的注释使用一下。
{ 0 word drop } : //
// 这是一个注释
真真真舒服,编译速度还提升了一些。
解决//不能空格的问题
其实和//贴贴也不是没有什么解决的办法,它的核心目的就是不让fift将他们识别成一个词汇。在fift中几乎一切指令的断言都是空格实现的,但它依然为我们提供了升级的方式。如(create):
它给了我们升级的机会:
操作 命令 等级 (create)
其实fift不仅仅只有上文提到的0和1两个级别,还有 2 3!
普通词素:不具有特殊行为,仅在调用时执行其定义。
活动词素:即使在编译状态下也会被执行。
前缀词素:可以修改词素的解析方式,允许在没有空格的情况下使用。
+2以上的就是前缀词汇。
{ 0 word drop } "//" 2 (create)
//完美哈哈哈哈
这样编译就通过了,//可以和单词贴贴了,多美的解决方式
更舒服的注释
当然,我们也可以实现其他的定义/*作为注释
{ "*/" word drop } "/*" 2 (create)
/* 真不错
哈哈哈哈
*/
当然我们可以定义更舒服(抽象)的注释,写到;;里面的注释
{ char ; word drop } ";" 2 (create)
;这种注释真的很舒服,有没有人懂;