顯示具有 JForthBlocks 標籤的文章。 顯示所有文章
顯示具有 JForthBlocks 標籤的文章。 顯示所有文章

2012年10月30日 星期二

JForthBlocks--Include Forth sourcecode file

Jimmy's papa已做好include積木,可引入並執行Forth檔,同時也加入註解"\"積木,為了JForthBlocks的Web環境,註解"\"積木花了不少時間修正,適應由積木產生的註解字串,而非只有來自檔案內容的註解

隨著JForthBlocks收錄的積木(Forth words)越來越多,Jimmy's papa實在很擔心會一時疏忽讓bug住了進來,有了include積木,Jimmy's papa就可以寫一些測試案例(Test Case)隨時測試
寄件者 scratchlab02
請直接將積木XML,貼至XML編輯區,便可見上圖出現的積木
<xml xmlns="http://www.w3.org/1999/xhtml"><block type="text_cquote" notchtype="LEFT_RIGHT" inline="false" x="1121" y="1274"><title name="STRING">./forth/testcase.f</title><value name="NEXTWORD"><block type="utility_include" notchtype="LEFT_RIGHT" inline="false"></block></value></block><block type="text_backslash" notchtype="LEFT_RIGHT" inline="false" x="1118" y="1316"><title name="STRING">Jimmyscratchlab 附註 執行測試案例</title></block></xml>
目前testcase.f的檔案內容
\ 試印出 99 乘法表 
: x 9 for cr r@ 9 for dup r@ * 2 .r space next drop next ; x

2012年10月17日 星期三

JForthBlocks--Forth說 I,J,K 即非 I,J,K 是名 I,J,K

Jimmy's papa為了讓Jimmy小朋友認認字,收收心,偶而會要他念幾頁金剛經,

經中須菩提有云
【 世尊說:我見、人見、眾生見、壽者見, “Because (when) the Tathagata speaks of the view of an ego, a Personality, a being and a life, 即非我見、人見、眾生見、壽者見,是名我見、人見、眾生見、壽者見 “it is not really, (but) is (expediently) called the view of an ego, a personality a being and a life.” 】。
雖然不甚了解此段經文的意義,反正是經典,小朋友有唸有保佑(BoBee)啦!!

不過今天寫Forth小範例時,使用Loop Index卻遇見非預期的結果,讓Jimmy's papa見識到了
Forth說 I,J,K 即非 I,J,K 是名 I,J,K
寫慣一般程式語言的人,或許看了書上的Forth程式碼會主觀認定I是最內迴圈索引,J是外迴圈索引,K是外外迴圈索引

不過事實上Forth的I,J,K是指返回堆疊(Return Stack)當下時間點實際暫存的迴圈體索引, 所以光看程式會以為外外迴圈的索引值要用K,但實際執行取索引值時,返回堆疊(Return Stack)或許只有外外迴圈一個迴圈體而已 ,所以只能用I取索引值
寄件者 scratchlab02
寄件者 scratchlab02
底下是XML,直接貼到XML編輯區,便能自動載入積木程式
<xml xmlns="http://www.w3.org/1999/xhtml"><block type="processing_Setup" notchtype="LEFT_RIGHT" inline="false" x="54" y="20"><value name="NEXTWORD"><block type="variable_value" notchtype="LEFT_RIGHT" inline="false"><title name="NAME">psjObj</title><value name="NEXTWORD"><block type="procedures_callnoreturn" notchtype="LEFT_RIGHT" inline="false"><mutation name="psjObj"></mutation><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">230</title><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">230</title><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">230</title><value name="NEXTWORD"><block type="processing_BackgroundByValues" notchtype="LEFT_RIGHT" inline="false"></block></value></block></value></block></value></block></value></block></value></block></value></block><block type="procedures_callnoreturn" notchtype="LEFT_RIGHT" inline="false" x="55" y="58"><mutation name="psjObj"></mutation><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">0</title><value name="NEXTWORD"><block type="processing_FillByGray" notchtype="LEFT_RIGHT" inline="false"></block></value></block></value></block><block type="compile_define_highword" notchtype="Top_Bottom_Right" inline="false" x="55" y="96"><title name="NAME">MyHighWord</title><statement name="STACK"><block type="math_PushNumber" notchtype="TOP_BOTTOM_RIGHT" inline="false"><title name="NUM">20</title><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">0</title></block></value><next><block type="control_DoLoop" notchtype="Top_Bottom_Right" inline="false"><statement name="STACK"><block type="control_i" notchtype="TOP_BOTTOM_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">2</title><value name="NEXTWORD"><block type="math_Mod" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_TwoSlash" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="comment" notchtype="LEFT_RIGHT" inline="false"><title name="COMMENT">為何用I不用J,這是Forth有趣的特性,因為此時間點Return Stack只存在一個迴圈體</title></block></value></block></value></block></value></block></value><next><block type="math_PushNumber" notchtype="TOP_BOTTOM_RIGHT" inline="false"><title name="NUM">25</title><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">0</title></block></value><next><block type="control_DoLoop" notchtype="Top_Bottom_Right" inline="false"><statement name="STACK"><block type="stack_dup" notchtype="TOP_BOTTOM"><next><block type="procedures_callnoreturn" notchtype="TOP_BOTTOM_RIGHT" inline="false"><mutation name="psjObj"></mutation><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">25</title><value name="NEXTWORD"><block type="control_j" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_Multi" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="stack_rot" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="control_i" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_Add" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">20</title><value name="NEXTWORD"><block type="math_Multi" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">20</title><value name="NEXTWORD"><block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false"><title name="NUM">8</title><value name="NEXTWORD"><block type="processing_DrawRect" notchtype="LEFT_RIGHT" inline="false"><value name="NEXTWORD"><block type="comment" notchtype="LEFT_RIGHT" inline="false"><title name="COMMENT">此I非彼I</title></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></value></block></next></block></statement><next><block type="stack_drop" notchtype="TOP_BOTTOM"></block></next></block></next></block></next></block></statement></block></next></block></statement></block><block type="procedures_callnoreturn" notchtype="LEFT_RIGHT" inline="false" x="58" y="431"><mutation name="MyHighWord"></mutation><value name="NEXTWORD"><block type="comment" notchtype="LEFT_RIGHT" inline="false"><title name="COMMENT">JimmyScratchLab Demo</title></block></value></block></xml>

2012年10月11日 星期四

JForthBlocks--使用[IF]...[ELSE]...[THEN]積木

使用[IF]...[ELSE]...[THEN]積木可以讓Forther選擇控制哪些程式碼段落需要編譯與解譯,哪些段落則不需要

在開發Library時,因為各個Forth系統不一定實作Library所用到的符式詞(Forth word),需要用到[IF]...[ELSE]...[THEN]積木適時補上缺漏

以下範例說明,如何選擇哪些段落需要執行,可到JForthBlocks線上試玩版 jforthblocks.appspot.com試玩看看

寄件者 scratchlab02
寄件者 scratchlab02

2012年9月26日 星期三

JForthBlocks--Import New Blocks(.FS檔自動轉成新積木)

萬歲!!!JForthBlocks終於可以將.FS檔(Forth Library File)自動轉成新積木了

幫JForthBlocks做新積木是件繁瑣又累人的差事,Jimmy's papa已經將這部份自動化,讓使用者自行載入自己定義的Forth Library檔案,便可自動產生新積木,不用再做苦工了,不知道其他的程式語言的函式庫轉積木的難度如何,改天Jimmy's papa試著轉轉看

打從第一次接觸MIT Scratch,Jimmy's papa就夢想有朝一日能在Scratch-like tool上有豐富的函式庫支援,JForthBlocks能成功邁向這個目標一小步,真的很感謝Blockly與JeForth等專案相關開發者的貢獻哩!!!

打開文字編輯器先定義如下的My Library.fs,並存檔
: 3dup dup dup dup ;
: 4dup dup dup dup dup ;
: 5dup dup dup dup dup dup ;

請按Import Library
寄件者 scratchlab02
寄件者 scratchlab02
寄件者 scratchlab02
寄件者 scratchlab02

2012年9月19日 星期三

JForthBlocks--測試有無DoLit的效能

在Forth裡DoLit指令是用來取字面值(literal)的巧妙機制,當定義高階詞時,如有字面值(literal)編入詞典時,會同時夾帶DoLit編入字面值(literal)的前一個位址,如此一來,當Forth執行到DoLit指令時,便會自動取下一個位址的字面值(literal),這技巧在以低階語言開發的Forth系統上很有效率

不過,JForthBlocks所依賴的以Javascript開發的JeForth,DoLit是否還保有同樣的優勢?

Jimmy's papa動手修改JeForth部份程式碼,再用JForthBlocks同一份積木程式,測試看看有無DoLit的效能,是否有很大的差異,底下是跑五百萬次迴圈的輸出結果,第一次跑出的結果,有無DoLit指令似乎只有幾百微秒(milliseconds)的差異,隨後兩次的結果,執行時間會爆增,或許是垃圾收集機制的干擾

首先,測試compilecode('doLit',n)的效能
        function call(xt){// high level definition inner execution loop
            highLevelLooping=true; ip=xt;
            do{
                var id=dictionary[ip++];
                //if(typeof(id)=='object'){var v=id['lit'];stack.push(v);continue;}
                ........
                ........            
            }
        }

        function exec(src){ //source code interpreting loop
            .....
            .....
            do{token=nexttoken(); word=token;
                var id=findword(token);
                ......
                ......    
                       if(typeof(n)==='string'||n<=0||n>0){
                        if(compiling)
                            compilecode('doLit',n);// compile an literal
                            //compilecode({lit : n});
                ......
                ......
            }while(error===0&&ntib<tib.length);}

          }
寄件者 scratchlab02
連續執行三次的結果




再來,測試compilecode({lit : n})的效能,執行時則統一由call(xt)代勞取字面值(literal)
        function call(xt){// high level definition inner execution loop
            highLevelLooping=true; ip=xt;
            do{
                var id=dictionary[ip++];
                if(typeof(id)=='object'){var v=id['lit'];stack.push(v);continue;}
                ........
                ........            
            }
        }

        function exec(src){ //source code interpreting loop
            .....
            .....
            do{token=nexttoken(); word=token;
                var id=findword(token);
                ......
                ......    
                       if(typeof(n)==='string'||n<=0||n>0){
                        if(compiling)
                            //compilecode('doLit',n);// compile an literal
                            compilecode({lit : n});
                ......
                ......
            }while(error===0&&ntib<tib.length);}

          }
寄件者 scratchlab02
連續執行三次的結果,看來三戰兩勝,以微幅差距領先



底下是積木的XML,可以貼到JForthBlocks的XML編輯區,便會將這次測試所用到的積木載入
<xml xmlns="http://www.w3.org/1999/xhtml">
  <block type="procedures_defnoreturn" notchtype="Top_Bottom_Right" inline="false" x="137" y="55">
    <title name="NAME">TestLiteral</title>
    <statement name="STACK">
      <block type="math_PushNumber" notchtype="TOP_BOTTOM">
        <title name="NUM">5000000</title>
        <next>
          <block type="control_ForNext" notchtype="Top_Bottom_Right" inline="false">
            <statement name="STACK">
              <block type="math_PushNumber" notchtype="TOP_BOTTOM_RIGHT" inline="false">
                <title name="NUM">0</title>
                <value name="NEXTWORD">
                  <block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false">
                    <title name="NUM">0</title>
                    <value name="NEXTWORD">
                      <block type="stack_2drop" notchtype="LEFT_RIGHT" inline="false"></block>
                    </value>
                  </block>
                </value>
                <next>
                  <block type="math_PushNumber" notchtype="TOP_BOTTOM_RIGHT" inline="false">
                    <title name="NUM">0</title>
                    <value name="NEXTWORD">
                      <block type="math_PushNumber" notchtype="LEFT_RIGHT" inline="false">
                        <title name="NUM">0</title>
                        <value name="NEXTWORD">
                          <block type="stack_2drop" notchtype="LEFT_RIGHT" inline="false"></block>
                        </value>
                      </block>
                    </value>
                  </block>
                </next>
              </block>
            </statement>
          </block>
        </next>
      </block>
    </statement>
  </block>
  <block type="utility_milliseconds" notchtype="LEFT_RIGHT" inline="false" x="89" y="289">
    <value name="NEXTWORD">
      <block type="procedures_callnoreturn" notchtype="LEFT_RIGHT" inline="false">
        <mutation name="TestLiteral"></mutation>
        <value name="NEXTWORD">
          <block type="utility_milliseconds" notchtype="LEFT_RIGHT" inline="false">
            <value name="NEXTWORD">
              <block type="stack_swap" notchtype="LEFT_RIGHT" inline="false">
                <value name="NEXTWORD">
                  <block type="math_Minus" notchtype="LEFT_RIGHT" inline="false">
                    <value name="NEXTWORD">
                      <block type="print_DotS" notchtype="LEFT_RIGHT" inline="false"></block>
                    </value>
                  </block>
                </value>
              </block>
            </value>
          </block>
        </value>
      </block>
    </value>
  </block>
</xml>

2012年9月11日 星期二

JForthBlocks--Linked List

目前JForthBlocks沒有高階的資料結構可用,或許過陣子引用其他現成的積木庫試試看效果如何,不過Jimmy's papa自己動手寫個簡單的連接串列,嗯!還蠻簡單的哩!!!

底下是配置ABCD四個記憶區塊,每個區塊都可儲存下一個連接地址與區塊紀錄的字串內容,ABCD區塊分別對應大野狼,大豬,二豬與豬小弟

不過區塊一多的話,就不能用這個法子,因為要幫每個區塊取名很麻煩!!!
寄件者 scratchlab02

2012年8月25日 星期六

JForthBlocks-以美味蟹堡當範例,八歲的Jimmy學如何使用堆疊指令

Jimmy's papa為了方便Jimmy小朋友能很快的進入狀況,以他喜歡看的卡通海綿寶寶當範例,先造好一些美味蟹堡製作手藝的中文程式積木,這樣一來他就可以專注在堆疊的操作學習上

在Jimmy小朋友邊try邊與我討論時,我也在觀察中文程式積木的命名,是否能讓小朋友快速理解單個積木的功能,再由多次嘗試錯誤的組裝過程,進一步對程式運作的原理心領神會

這段是Jimmy小朋友親自操作解說的


這整段是合集

2012年8月9日 星期四

JForthBlocks--Define Chinese High Word以中文定義新積木

之前JForthBlocks以中文定義新積木是無法執行,原因是引用中文積木時產生的Javascript code會有亂碼,Jimmy's papa已修正這個bug

寄件者 scratchlab02

2012年8月5日 星期日

JForthBlocks--POSTPONE與WORD的練習

這是Jimmy's papa試著解決網友提出的問題,順便當作自己的練習,也幫JForthBlocks補上了BL及WORD幾個積木

POSTPONE--可延遲立即詞(immediate words)在編譯狀態不會立即執行
WORD--依置於堆疊頂端的限定字元,解析WORD後面的字串,然後將解析好的字串置入堆疊
寄件者 scratchlab02
寄件者 scratchlab02
由於Mary尚未定義,所以不能編譯
寄件者 scratchlab02
在解譯狀態下,Mary可作為Greeting解析的對象
寄件者 scratchlab02

2012年5月31日 星期四

JForthBlocks--用see積木幫有Create...Does>積木照張X光,果然有物件繼承的fu喔~~

Jimmy's papa查閱許多文件也看了JeForth的JS原始碼,一直搞不懂create...does>積木的運作原理,但為了搞懂如何做出Object-Oriented Forth,只好動用了Forth的X光機--see積木

底下的實驗Jimmy's papa做了個const高階積木,接著將0指定給a積木,1000指定給b積木,雖然目前用see積木還看不大清楚所有積木內部構造,但依實驗結果大約可知,const積木裡面的does>編譯後竟然變成does r>

而更有趣的是,a積木(ip位址在132)與b積木(ip位址在136)執行到最後,都會往前跳到ip位址127,也就是共用在does後面的r> @ >r r> exit,神奇吧!!!
寄件者 scratchlab02
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼,有空再附上註解
: const create , 0 , does> @ >r r> ; 0 const a 1000 const b see const see a see b create cc 11 , 22 , see cc ' const ' a ' b ' cc a b .s

2012年5月23日 星期三

JForthBlocks--execute指令

Jimmy's papa今天測試execute指令,
先以 '積木測測看能否取得 *積木的序號id
寄件者 scratchlab02
取得*積木的序號id是6
寄件者 scratchlab02
接著將7與5推入堆疊,然後將序號id 6 挪到堆疊頂端,讓execute積木執行
寄件者 scratchlab02
最後執行結果是35,等同於執行 7 5 *
寄件者 scratchlab02
這是產生出來的Forth原始碼
' * .s 7 5 rot execute .

2012年5月18日 星期五

JForthBlocks--控制結構begin..until

Jimmy's papa接下來要學習如何使用Forth的begin..until控制結構積木,只能在定義(編譯)高階積木時使用,且begin積木until積木必須成對使用

積木用法 begin [code] ( flag ) until

Jimmy's papa照舊先拉一拉積木作個實驗,讓程式由10遞減到0,並逐一推入堆疊,最後以.s積木列印在螢幕
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test begin dup 1- dup 0 = until ; 10 test .s

2012年5月16日 星期三

JForthBlocks--控制結構do..loop

Jimmy's papa接下來要學習如何使用Forth的do..loop控制結構(Control Structure)積木,這類積木只能在定義(編譯)高階積木時使用,不能用在解譯時期,且do積木loop積木必須成對使用,do..loop積木之間可巢狀內含其他的do..loop積木,不過最多三層,因為Forth僅提供i j k三個迴圈計數索引(loop index)

為什麼只提供三個呢?或許長久以來Forth擅長用來開發短小精悍的應用,所以有人認為三個就夠用了,不過Jimmy's papa認為只提供這三個迴圈計數索引,可能是因為寄存在返回堆疊(Return Stack)的關係,某些書上還建議,操作堆疊的深度盡量避免超過三個

控制結構do..loop,可用的積木有..

do積木,從資料堆疊取上限值(limit)及起始值(startindex),至少會執行一次迴圈
?do積木,若上限值(limit)等於起始值(startindex),則不會執行迴圈
i積木,會將目前迴圈計數索引值從返回堆疊(Return Stack)複製到資料堆疊(Data Stack)
loop積木, 將迴圈計數索引值遞增1
+loop積木,從資料堆疊取遞增值,加總到迴圈計數索引值

Jimmy's papa先拉一拉積木作個實驗,讓程式從0開始跑10次迴圈,並將每次的索引值(loop index)推入資料堆疊,最後以.s積木列印在螢幕
寄件者 scratchlab02
執行結果會印出堆疊所有數值 0 1 2 3 4 5 6 7 8 9
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test 10 0 do i loop ; test .s


接著測試?do積木,上限值(limit)及起始值(startindex)皆為0
寄件者 scratchlab02
執行結果,堆疊是空的(empty)
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test 0 0 ?do i loop ; test .s


最後測試一下+loop積木,每次迴圈索引值(loop index)遞增3
寄件者 scratchlab02
執行結果
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test 99 0 do i 3 +loop ; test .s

2012年5月15日 星期二

JForthBlocks--控制結構IF..ELSE..THEN

Jimmy's papa今天學習如何使用Forth的if..then控制結構(Control Structure)積木,這類積木只能在定義(編譯)高階積木時使用,不能用在解譯時期,且if積木與then積木必須成對使用,if..then積木之間可巢狀內含其他的if..then積木

由於Forth後置語法的關係,邏輯條件運算必需先於if積木完成,if積木會取堆疊頂端值(Top of Stack),若數值不為0,則為真(True),若數值等於0,則為假(False)
下面是Jimmy's papa拉一拉積木,所做的範例
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test if s" TOS is non-zero" then ; 1 test .s
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test if s" TOS is non-zero" then ; 0 test .s
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test if s" TOS is non-zero." else s" TOS is zero." then ; 1 test 0 test .s
執行exit積木,Forth將從目前的高階積木離開,此動作會清掉返回堆疊(Return Stack)頂端, 所以若高階積木有用到>r積木將資料暫存於返回堆疊(Return Stack),則需在執行exit積木之前, 先執行r>積木將暫存資料從返回堆疊(Return Stack)移回資料堆疊(Data Stack)
寄件者 scratchlab02
寄件者 scratchlab02
這是產生出來的Forth原始碼
: test dup 1 = if drop s" one" exit then 2 = if s" two" exit then ; 2 test .s