: LIT ( - n ) 編譯數字的運行時間代碼 R@ @ 取出編譯在詞身內的數字 R> 2+ >R ; 調整IP 運行時 LIT 作兩項工做: 一、它必須把跟着它的數字放到參數堆棧頂; 二、它必須移動解釋指針 IP 越過這個數字而指向下一個編譯地址。 |
: FIVE+ 5 + ;
|
開始執行 LIT 以前,IP 偏移指向 5 。即(IP)=1002。執行 LIT,因爲 LIT 是冒號定義,因此先執行的是 LIT 的代碼指針域 cfa 內的 NEST,執行過程: 一、(IP) -> 返回棧頂保存,因而返回棧首項的內容爲1002 二、(W)+2 -> W 它是 LIT 的 pfa 三、(W) -> IP 四、執行 NEST 內最後的 NEXT ,因而就開始執行 LIT 的詞身 |
^R@ 把返回棧頂的內容1002複製到參數棧頂 ^@ 取出1002單元的內容5 ^R> 把返回棧頂的1002送到參數棧頂 ^2+ 參數棧首項變爲1004,指着下一個要執行的詞 + ^>R 把1004送回返回棧頂保存 ^UNNEST 把返回棧頂的1004 -> IP,接着執行1004處的 +。 |
: COMPILE ( - ) 只能夠用在冒號定義內部。當該冒號定義執行時,COMPILE 就把跟在它後面的定義編譯進詞典中。 R> DUP 2+ >R @ , ; 與 LIT 定義相比,COMPILE 僅僅在定義的最後多了一個逗號,由它把留在堆棧頂上的跟在 COMPILE 以後的詞的 cfa 編入詞典 |
: LITERAL ( n - ) 把在參數棧上的單字長整數編譯成爲一個文字常數。 COMPILE LIT 首先編譯運行時間代碼 LIT , 接着編譯數字自己 ; IMMEDIATE 使其成爲當即詞 |
eg: : test [ 5 ] LITERAL + ; //數字 5 必須處於詞 [ 和 ] 中間。 |
: DLITERAL ( d - ) 把在參數棧上的雙字長整數編譯成爲一個雙字長的文字常量 SWAP 顛倒雙字長整數的次序 [COMPILE] LITERAL 把文字常數的編譯推遲到 DLITERAL 執行時進行。由於 LITERAL 是當即詞,故只有用[COMPILE]才能把它編入 DLITERAL 中。 [COMPILE] LITERAL 強行編譯雙字長文字常數的高16位。 ; IMMEDIATE |
: [COMPILE] ( - ) 強行編譯跟着的當即型定義 ' 尋求跟着的詞的執行地址 , 編譯它 ; IMMEDIATE 必須當即執行 |
: : ( - ) 定義一個高級定義,新定義完成以前被"隱藏"起來,冒號的執行代碼給程序增添一層嵌套 !CSP 把當前參數堆棧指針存入變量CSP以在定義結束時查錯之用,正常編譯不該影響參數堆棧的深度 CURRENT @ CONTEXT ! 使 context 詞彙與 current 詞彙一致 CREATE 使用跟在冒號後面的名字在詞典中創建一個首部 HIDE 使該首部躲過詞典搜索 ] 進入冒號定義的編譯程序,開始建造在參數域中的執行地址表 ;USES 把跟着的代碼程序(即下面的NEST)的地址插入到新定義的代碼指針域,使新定義成爲一個冒號定義。(相似DOES>,編譯運行過程已經規定好的代碼到代碼域) NEST , 編譯地址解釋程序NEST的地址,使其可被放進新定義的cfa |
: ; ( - ) 結束一個冒號定義,它編譯執行代碼UNNEST退出一層件嵌套,改變STATE的值以解釋編譯 ?CSP 當前的參數堆棧指針與CSP的值相符嗎?若不相符則中止 COMPILE UNNEST 給新定義的末尾加上UNNEST,使程序的執行返回到調用者 REVEAL 與HIDE想反操做 [COMPILE] [ 在此外編譯,[ 以結束新定義的編譯 ; IMMEDIATE 分號自身必須在編譯狀態下執行,因此必須是一個當即詞。 |
: ASCII ( - char ) 把輸入流中下一個字符的ASCII代碼編譯爲一個數字文字常量 BL WORD 取出下一個字符 1+ C@ 獲得它的ASCII代碼 STATE @ 獲取當前系統狀態(編譯?解釋) IF [COMPILE] LITERAL 編譯狀態就把其編爲文字常數 THEN 不然留在參數堆棧上 ; IMMEDIATE |
|
: ['] ( - ) ' [COMPILE] LITERAL ; IMMEDIATE |
['] 被定義成爲一個當即型的定義,所以對於 ['] 定義內的 ' 來講,所謂的輸入流中的下一個詞就是冒號定義內跟在 ['] 後面的那個詞。 |
: HOLD ( char - ) 把ASCII字符char插入輸出字符串中 -1 HLD +! HLD爲指向輸出文本緩衝區的字符指針,在輸出文本緩衝區中造成輸出數字字符串。數字字符串是從最低有效位開始逆向創建,爲把一個字符插入該字符串。HLD 的內容要減一 HLD @ 取到指定地址 C! ; 把字符串插入HLD所指定的地址字節 |
: <# ( - ) 初始化數字轉換過程,要求棧中是個無符號雙字長數 PAD 返回輸出文本的緩衝區地址 HLD ! ; HLD 指向 PAD ,以便字符串能在 PAD 緩衝區中創建 |
: #> ( d - addr len ) 結束輸出數字轉換,並把字符串的地址和長度送入堆棧,它們正是 TYPE 命令所須要的參數 2DROP 再也不須要堆棧中的雙字長數 HLD @ 取出字符串首址 PAD 取出字符串的末尾地址 OVER - ; 獲得字符串的長度 |
: SIGN ( n - ) 若是棧頂項 n 是負數,則在輸出數字字符串中插入一個負號 0< IF 判斷棧頂是否是負數 ASCII - HOLD 插入負號 THEN ; |
: # ( d1 - d2 ) 轉換一位數字,並把它加到輸出數字字符串中。轉換中,d1除以基,商d2被保留在堆棧中,餘數被轉換成ASCII碼,送入輸出緩衝區 BASE @ MU/MOD 餘數和雙字長整數商保留在堆棧上 ROT 把餘數移到棧頂 9 OVER < 如果餘數大於9 IF 7 + THEN 加7以造成A ASCII 0 + HOLD ; 把餘數轉換成 ASCII 碼,並插入到輸出緩衝區 |
: #S ( d - 0 0 ) 轉換一個雙字長整數,直至結果爲零 BEGIN # 轉換一位數字 2DUP OR 判斷商是否爲 0 ? 0= UNTIL ; 若是商爲零,退出循環;不然,繼續轉換。 |
eg:無符號雙字長整數 12345. ,要求打印成:123.45 ; 命令:<# # # ASCII . HOLD #s #> TYPE 小數點的前三位整數用 #S 實現轉換。整個轉換過程是在 PAD 緩衝區內進行的。轉換完成堆棧頂部存放的是ASCII字符串的首地址和長度。 |