零.一版是沒法自舉的,它甚至難以稱之為「咒」。「咒」必須圖靈完備,圖靈完備之後,才有條件自舉。
在零.二版,貧道將嘗試定義一極度簡單但圖靈完備的法咒。
圖靈完備
圖靈機有一套嚴謹的符號定義,但貧道不打算在此細述,首先,雖然當代電腦/通用法咒(程式語言)都圖靈完備,但這套原始的符號定義與現今的計算機/法咒有不小的差異,需要一些推導才能證明兩者是等價的。
基本上,首先想像有一個「咒指針」指向法咒正在執行的行數,法咒只要有語句能控制
- 循序,即咒會一行一行往下執行(咒指針遞增)
- 修改記憶體狀態
- 決策,可根據「條件」決定咒指針要跳躍至何處
- 這個「條件」是「當下記憶體狀態」的函數
就圖靈完備了。
編譯器生成真言後,放到真實機器上本就會逐步執行,因此循序不會是問題,只要檢視後兩條即可
以 C 語言為例
- 賦值語句能修改記憶體狀態
if
搭配goto
能根據條件選擇性跳躍到任意一行
決策有很多種實現,if
必不可少,用 if
搭配 goto
當然是最直觀符合定義的,但 while
也能取代 goto
,可證明 while
與 goto
的能力等價。思路是嘗試找到一種方法把 while
轉換為 goto
,同時找到一套方法把 goto
轉換為 while
。
除了 goto
與 while
,遞迴也是一種與 if
搭配來達到圖靈完備的方法。道友可嘗試將 while
與遞迴互相轉化來證明。
而多數流行的法咒會同時提供 while
與遞迴,乃至迭代器、for
迴圈等等語句,什麼好寫就支援什麼。
設計
零.一版音界咒已有循序與修改記憶體的能力,再加上決策語句便能完備。
音界咒零.二版選擇的是遞迴,想必道友們並不會太意外,畢竟那句古老的偈語早就深植人心:
遞迴只應天上有,人間該當用迴圈。
在符合「離塵」的寓意之外,實現遞迴也就意味著實現了術(函式)此一重要的模組化工具,為構造較大型的程式打下了基礎,其泛用程度相較 goto
、while
又高上了一檔。
概述
零.二版新增「若」語句,以及「術」的定義與施展(調用),並支援「外術」(外部函式),以實現標準輸入輸出。
為輔助「若」語句的使用,亦加入相等、不等、小於......等等比較算子。
檔案的頂層僅允許變數宣告與術宣告,編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展初
術。
新增算子
比較運算
==
- 等於
!=
- 異於
<=
- 小於或等於
>=
- 大於或等於
>
- 大於
<
- 小於
以上算子的求值結果皆為整數,若式子成立,值為1,否則值為0。運算優先級彼此相等,但比加減乘除都還要低。
餘數
%
取餘數。優先級介於乘除與加減間。
「若」語句
若(甲==乙)【
...
】
在括號內條件不為0時,執行【 】內語句,括號內為0時,注意到括號內並不限定是比較算子,可以是任意算式,乃至數字或變數。
貧道不採用塵界常見的花括號,是因為全形的花括號並不容易與圓括號區分,貧道自用的微軟正黑體是如此,恐此問題普遍存在,故採【 】
,此類括號似乎沒有通用的念法,在此給它取個名吧!
道友請看,此括號一面平,一面弧,若置平面朝下、弧面朝上,便好似能擺放蛋或球體的基座。故吾名之曰基座括號或簡稱基括號。
與「若」連用的尚有「或若」、「不然」兩關鍵字。
若(甲>10)【
...
】或若(乙==1)【
...
】或若(乙==0)【
...
】不然【
...
】
# 決策結尾
此結構中,唯有當上一層的條件不符合時,才會嘗試下個括號內的條件並執行基括號內的語句。例如,以上法咒唯有在「甲<=10」時才會去檢查「乙==1」,當所有條件都不成立時,就執行不然
基括號內的語句。
術
術.輾轉相除(甲、乙)【
若(乙==0)【
歸.甲
】
歸.輾轉相除(乙、甲%乙)
】
上例展示一遞迴術——輾轉相除術,以下逐詞解釋:
術
:關鍵字,由此開頭,定義一術.
:音界號,用以區隔關鍵字與術名輾轉相除
:術名(甲、乙)
:參數列表,參數之間以頓號、
為間隔【
:左基括號,術體開始若(乙==0)【 歸.甲 】
:符合條件時,將甲作為術的求值結果(歸值),結束術。歸.輾轉相除(乙、甲%乙)
:施展輾轉相除(乙、甲%乙)
,以其歸值為歸值,結束術。】
:右基括號,術體結束
在零.二版中,術的參數與歸值(回傳值)都是整數。若在任意分支中,術沒有歸值,編譯器應報錯。
作用域
術在定義之後才能使用,也就是說,不支援術的互相調用。
以下法咒是非法的。
術.甲()【 】
術.乙()【甲()】
外術(外部函式)
支援 曰(數)
此一外術,其接受一個整數作為參數,執行後會將該整數送進標準輸出。
法咒執行流程
編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展初
術。若檔案中無初
術,編譯失敗。