- Forth เริ่มต้นจาก อินเทอร์พรีเตอร์ขนาดเล็ก ที่ Chuck Moore สร้างขึ้นเพื่อลดขั้นตอนการคอมไพล์และการใช้ punch card ที่ยาวซับซ้อน ก่อนจะเติบโตเป็นระบบที่ดูดรวมทั้งตัวแก้ไขข้อความ ระบบปฏิบัติการ และคอมไพเลอร์เข้าไว้ด้วยกัน
- รูปแบบการเขียนแบบ postfix (RPN), data stack และ word (dictionary) ไม่ใช่ไวยากรณ์ประหลาด แต่เป็นการออกแบบเพื่อลดความสิ้นเปลืองและงานซ้ำบน ฮาร์ดแวร์ที่มีข้อจำกัดสูง
- แก่นของ Forth อยู่ที่ โครงสร้างที่บูตสแตรปได้ ซึ่งทำให้สามารถนิยามและนิยามใหม่ได้จากภายในภาษาเอง แม้แต่ส่วนประกอบอย่าง
:, ;, IF, คอมเมนต์ และตัวแปร
- อิมพลีเมนเทชันอย่าง JonesForth,
nasmjf, PlanckForth และ sectorforth แสดงให้เห็นว่า Forth สามารถเริ่มต้นจากขนาดเพียงหลักสิบถึงหลักร้อยไบต์ หรือจาก primitive เพียงไม่กี่ตัว แล้วขยายไปเป็นอินเทอร์พรีเตอร์ คอมไพเลอร์ แอสเซมเบลอร์ และ DSL ได้
- กรณีของยานอวกาศ, Open Firmware, Jupiter Ace, Canon Cat, Harris RTX2010 และ GreenArrays แสดงให้เห็นว่า Forth สอดคล้องอย่างมากกับ การพัฒนาแบบอินเทอร์แอ็กทีฟ, โค้ดขนาดเล็ก, ความเป็นมิตรต่อฮาร์ดแวร์ และการประมวลผลพลังงานต่ำ
จุดเริ่มต้นจากตำนาน Usenet สู่การสำรวจ Forth
- Dave Gauer ได้เรียบเรียงการเดินทางส่วนตัวในการค้นพบ Forth และวางมันไว้ในบริบทของประวัติศาสตร์คอมพิวเตอร์ โดยหน้านี้ดัดแปลงมาจากสไลด์การบรรยายสั้น
- ในยุค 1990 กลุ่ม
comp.* บน Usenet โดยเฉพาะ comp.lang.* เป็นพื้นที่สำคัญสำหรับการเรียนรู้และถกเถียงเรื่องการเขียนโปรแกรม
- มีการยกตัวอย่างว่าประกาศเปิดตัว Linux ครั้งแรกของ Linus Torvalds ก็ถูกโพสต์บน
comp.os.minix ในปี 1991
- ช่วงปลายทศวรรษ 1990 Perl มีบทบาทสูงมากบนเว็บยุคแรกในฐานะภาษาสำหรับหน้าแบบไดนามิกและการประมวลผลฟอร์มผ่าน CGI
- ตำนานที่พบในยุค Usenet เช่นภาษาในตระกูล Lisp, Y combinator, The Little Schemer และ The Story of Mel นำไปสู่ความสนใจใน Forth
- ในตอนแรก Forth ปรากฏขึ้นผ่านเรื่องเล่าว่าเป็น “ภาษาที่ยืดหยุ่นพอจะเปลี่ยนค่าของจำนวนเต็มได้” และ Chuck Moore ก็ถูกจดจำเหมือน “mad wizard” ที่สามารถเขียนโปรแกรมอะไรก็ได้ด้วยโค้ดเพียงไม่กี่หน้าจอ
- ซีรีส์บล็อก programming in the twenty-first century ของ James Hague กลายเป็นแรงกระตุ้นสุดท้ายให้เริ่มสำรวจ Forth
RPN และสแต็กเป็นเพียงจุดเริ่มต้น
- ความประทับใจแรกของ Forth คือ รูปแบบการเขียนแบบ postfix หรือ Reverse Polish Notation (RPN)
- ต่างจากรูปแบบ infix ทั่วไปอย่าง
3 + 4 Forth วางตัวดำเนินการไว้หลังตัวถูกดำเนินการ เช่น 3 4 +
- ตัวอย่างใน Forth
3 4 * 5 6 * + . จะแสดงผล 42
- ใน
dc การคำนวณเดียวกันเขียนได้เป็น 3 4 * 5 6 * + p
- RPN ทำให้สามารถคำนวณนิพจน์ที่ซ้อนกันได้ตามลำดับที่ต้องการโดยไม่ต้องใช้วงเล็บ
3 4 * ให้ค่า 12, 5 6 * ให้ค่า 30 และ + ตัวสุดท้ายทำให้ได้ 42
- ใน Forth
. จะดึงค่าออกจากสแต็กแล้วพิมพ์ออกมา
- เครื่องคิดเลข HP-35 เป็นตัวอย่างสำคัญทางประวัติศาสตร์ที่ทำให้ RPN เป็นที่รู้จักนอกวงการวิทยาการคอมพิวเตอร์
- ช่วงต้นทศวรรษ 1970 HP มีเครื่องคิดเลขตั้งโต๊ะที่ทรงพลังอยู่แล้ว และ HP-35 ถูกยกเป็นตัวอย่างของการนำความสามารถนั้นมาใส่ไว้ในเครื่องคิดเลข “shirt pocket”
- เครื่องคิดเลขของ HP มีชื่อเสียงจากไวยากรณ์แบบ RPN และแม้ RPN จะมีประสิทธิภาพ แต่สำหรับคนนอกก็ดูเข้าใจยากพอสมควร
- ลักษณะเด่นข้อที่สองคือ data stack
- การทำงานอย่าง
PUSH, POP, SWAP, DUP ก็เป็น word ของ Forth ด้วย
- เมื่อป้อนตัวเลข ค่านั้นจะถูกวางบนสแต็ก และตัวดำเนินการจะดึงค่าจากสแต็กไปคำนวณก่อนนำผลลัพธ์วางกลับเข้าไป
- สแต็กช่วยลดความจำเป็นในการตั้งชื่อให้ค่ากลาง
- ในภาษา imperative หลายภาษา มักต้องมีชื่อชั่วคราวอย่าง
result2, matched_part3
- วิธีทำงานแบบไม่ตั้งชื่อนี้ยังถูกเรียกว่า implicit, tacit หรือ point-free programming
- การเข้าใจ Forth ด้วยแค่ RPN และสแต็กยังไม่เพียงพอ แต่ก็ถือเป็นจุดตั้งต้นที่เหมาะสมสำหรับทำความเข้าใจที่มาทางประวัติศาสตร์
Concatenative programming, Joy และความต่างของ Forth
- เมื่อศึกษาลึกลงไปใน Forth ก็มักจะได้พบแนวคิดเรื่อง concatenative programming
- ตัวอย่างแบบ applicative คือ
eat(bake(prove(mix(ingredients))))
- ตัวอย่างแบบ concatenative คือ
ingredients mix prove bake eat
- ฟังก์ชันถูกเรียงต่อกันตามลำดับ และค่าจากแต่ละขั้นจะถูกส่งต่อไปยังขั้นถัดไปโดยปริยาย
- Joy เป็นตัวอย่างเด่นของ concatenative language
- Manfred von Thun ได้แรงบันดาลใจจากปาฐกถา ACM Turing Award ปี 1977 ของ John Backus เรื่อง “Can Programming Be Liberated from the von Neumann Style?”
- ใน Joy ทุกฟังก์ชันรับสแต็กหนึ่งก้อนเป็นอินพุต และคืนสแต็กหนึ่งก้อนเป็นเอาต์พุต
- โปรแกรมคือรายการของฟังก์ชันที่อ่านจากซ้ายไปขวา
- quotation และ combinator ของ Joy แสดงให้เห็นวิธีคำนวณแบบไร้ตัวแปร
- ใน JavaScript
[1, 2, 3, 4].map(n => n + 1) จะได้ [2,3,4,5]
- ใน Joy สามารถได้ผลเดียวกันด้วย
[1 2 3 4] [1 +] map
[] ใน Joy เป็นกลไก quotation ที่เก็บได้ทั้งข้อมูลและโปรแกรม ไม่ใช่แค่ข้อมูล
- Combinator ถูกมองเป็น higher-order function ที่รับฟังก์ชันเป็นอินพุต
map() เป็นตัวอย่างของการนามธรรมแพตเทิร์นสำเร็จรูปสำหรับการวนผ่านลิสต์
- combinator อย่าง
I, K, S และ SKI calculus ปรากฏขึ้นในฐานะโครงสร้างที่ใช้อธิบายการคำนวณสากล
- แค่
S และ K ก็เพียงพอจะสร้างระบบที่สมบูรณ์สำหรับการคำนวณสากลได้
- Forth เองก็สามารถสร้าง higher-order function ได้ผ่าน execution token และ word
EXECUTE
FOO EXECUTE จะรัน word ที่ word FOO ส่งกลับมา
- สามารถนิยาม word เชิง combinatorial อย่าง
MAP, FOLD, REDUCE ได้
- แม้ Forth กับ Joy จะมีไวยากรณ์ภายนอกคล้ายกัน แต่แนวทางตีความนิพจน์ต่างกัน
- ใน Forth
2 3 + ถูกอ่านว่า “push 2 และ 3 ลงสแต็กแล้วนำมาบวกกัน”
- ใน Joy จะถูกอ่านว่า “composition ของฟังก์ชัน 2, 3 และ + เทียบเท่ากับฟังก์ชัน 5”
- Forth เป็นภาษาที่เติบโตขึ้นจาก การปฏิสัมพันธ์กับฮาร์ดแวร์ มากกว่าจะยึดหลักการเชิงนามธรรมของ concatenative computing
เส้นทางที่ Chuck Moore สร้าง Forth
- ในปี 1958 Chuck Moore ใช้ Fortran และ IBM 704 ระหว่างช่วงที่อยู่กับ Smithsonian Astrophysical Observatory และ MIT
- Moore กล่าวไว้ใน
Forth, the Early years ว่า “Compiling took 30 minutes...you got one shot per day”
- มีการอ้างถึงด้วยว่า IBM 704 เป็นคอมพิวเตอร์หลอดสุญญากาศขนาดเต็มห้อง และโดยเฉลี่ยเสียทุกประมาณ 8 ชั่วโมง
- Moore สร้างอินเทอร์พรีเตอร์แบบง่ายที่อ่านการ์ดซึ่งควบคุมโปรแกรม เพื่อลดการคอมไพล์ซ้ำ
- ทำให้สามารถจัดชุดสมการที่ต่างกันสำหรับหลาย satellite ได้โดยไม่ต้อง recompile
- รูปแบบอินพุตแบบ free-form เชื่อถือได้มากกว่าคอลัมน์ที่ฟอร์แมตตายตัวของ Fortran สำหรับการเขียนโดยมนุษย์
- ระบบนี้กลายเป็นต้นกำเนิดของระบบที่ภายหลังถูกเรียกว่า Forth
- ในปี 1961 ที่ Stanford Moore ใช้ Burroughs B5500 และเขียน mathematical application ชื่อ CURVE
- CURVE มี interpreter ที่ซับซ้อนขึ้น, data stack และ control flow operator
- ความสามารถโดยคร่าว ๆ เทียบได้กับ Forth word อย่าง
IF ELSE DUP DROP SWAP + - *
- มีการเพิ่ม parameter stack และความสามารถในการนิยาม procedure ใหม่ ทำให้เริ่มมีโครงสร้างที่ใกล้กับ Forth
- ราวปี 1965 เมื่อเกิดสภาพแวดล้อม teletype, paper tape, timesharing และ interactive terminal ขึ้น Forth ก็มีความโต้ตอบมากขึ้น
- มีการเพิ่ม word อย่าง
KEY, EMIT, CR, SPACE, DIGIT
- word เหล่านี้เปลี่ยนระบบของ Moore ให้กลายเป็น program editor และผู้ใช้สามารถแก้ไข program ภายใน program ได้
- ในปี 1968 ที่ Mohasco Moore ทำงานกับ IBM 1130 และตั้งชื่อว่า “FORTH”
- IBM 1130 เป็นระบบ 16 บิต พร้อม RAM 8KB และจำกัดชื่อไฟล์ไว้ที่ 5 ตัวอักษร
- ระบบ “fourth generation” ของ Moore จึงกลายเป็น
FORTH เพราะข้อจำกัด 5 ตัวอักษร
- ช่วงเวลานี้มีการเพิ่ม return call stack และ word dictionary
- word dictionary แบบมีชื่อของ Forth ทำหน้าที่เป็น abstraction หลัก
: DOUBLE DUP + ;
: QUAD DOUBLE DOUBLE ;
- หากไม่มี return stack ก็จะไม่สามารถกลับไปยังตำแหน่งที่เหลือของ
QUAD ได้หลังจากรัน DOUBLE
NRAO, การพอร์ต, และ indirect threaded code
- ช่วงต้นทศวรรษ 1970 Moore เขียนซอฟต์แวร์ควบคุมคอมพิวเตอร์สำหรับ radio telescope ที่ National Radio Astronomy Observatory
- NRAO มีนโยบายให้ใช้ Fortran บน minicomputer แต่ Moore ได้รับอนุญาตให้ใช้ Forth จากความสำเร็จก่อนหน้านั้น
- ในงาน spectral-line observing สามารถแสดง spectra ที่กำลังเก็บข้อมูลอยู่ และ fit line-shapes ด้วย least-squares ได้
- งานนี้ผลักดัน state-of-the-art ของ online data reduction และนักดาราศาสตร์ก็นำไปใช้ค้นพบและทำแผนที่ inter-stellar molecules
- Elizabeth “Bess” Rather ยอมรับ Forth และเขียน Forth manual ฉบับแรกในปี 1972
- ต่อมาเธอร่วมก่อตั้ง FORTH, Inc กับ Chuck Moore
- จนเกษียณในปี 2006 เธอยังคงเป็นหนึ่งในผู้เชี่ยวชาญและผู้ผลักดันหลักของภาษา Forth
- Forth ถูกพอร์ตไปยังหลายเครื่อง เช่น IBM 360/50, Honeywell 316, Honeywell DDP-116, DEC PDP-11
- Forth implementation สำหรับ H316 ถูกพัฒนาอยู่บนคอมพิวเตอร์เครื่องนั้นเอง และถูกใช้เพื่อสร้าง Forth ตัวอื่น ๆ จึงถือเป็น implementation แบบ complete และ stand-alone ตัวแรก
- PDP-11 เป็น minicomputer สำคัญที่เชื่อมโยงกับประวัติศาสตร์ของ Unix และภาษา C
- เบื้องหลังที่ทำให้พอร์ตไปหลายเครื่องได้คือ indirect threaded code
- ในที่นี้ threaded code ไม่เกี่ยวกับ concurrency หรือ multi-threaded programming
- threaded code เก็บรายการ address ของ subroutine แทน instruction สำหรับเรียก subroutine
- การรันรายการ address นี้ต้องมี code interpreter
- indirect threaded code เก็บรายการ address ที่ชี้ไปยัง address ซึ่งชี้ไปยัง code อีกทอดหนึ่ง ไม่ได้ชี้ไปยัง code โดยตรง
- indirection ชั้นที่สองนี้ทำให้สามารถมี inner interpreter แยกต่างหากสำหรับแต่ละชนิดของ subroutine ได้
- ใน Forth นั้น outer interpreter คือส่วนที่ผู้ใช้โต้ตอบผ่าน terminal ส่วน inner interpreter จะรันส่วนที่เหลือของ word
- ณ จุดนี้ Forth ได้ขยายจาก command interpreter แบบง่าย ไปเป็นทั้ง interactive language, editor, operating system และวิธีเก็บกับรันโค้ด
- มีการสรุปคุณลักษณะว่าเป็น postfix notation, stack-oriented, concatenative style, interpreted, ปรับตัวเข้ากับ machine architecture ได้สูง, และมีขนาดกะทัดรัดมาก
- Forth ไม่ใช่ภาษาที่ถูกออกแบบขึ้นครั้งเดียวในปี 1958 แต่เป็นผลลัพธ์ที่ Moore ค่อย ๆ ทำให้เติบโตตามความต้องการของตนเองและฮาร์ดแวร์ใหม่
หากอยากเข้าใจ Forth ก็ต้อง implement Forth
- ในคำแนะนำ “To understand Forth, you have to implement a Forth” คำที่สำคัญคือ a Forth
- จากมุมมองของ Chuck Moore ระบบ Forth จะดีที่สุดเมื่อถูกปรับแต่งให้เหมาะกับ system และ task นั้น ๆ โดยเฉพาะ
- ก่อนจะลงมือกับซอร์สของ JonesForth ผู้เขียนได้ทำ Assembly Nights เพื่อเรียนพื้นฐาน assembly และ Linux ABI
- JonesForth ใช้ซอร์ส i386 assembly ที่เขียนด้วย GNU GAS assembler
- รองรับเฉพาะ 32-bit และใช้ Linux system call ABI โดยตรง
- ผู้เขียนใช้เวลาราว 1 ปีในการพอร์ต JonesForth เป็นสำเนาที่ทำงานด้วย NASM assembler และพอร์ตนี้คือ
nasmjf
- ระหว่างการพอร์ต
nasmjf ผู้เขียนได้เรียนรู้วิธีทำงานของ indirect threaded Forth แบบดั้งเดิม
jonesforth.S ของ JonesForth เป็นไฟล์เดียวที่เก็บส่วน assembly และ Richard W.M. Jones อธิบายลำดับการทำงานของ interpreter ด้วย ASCII art และคำอธิบาย
- ผู้เขียนจึงเขียนไดอะแกรม ASCII art จำนวนมากไว้ในซอร์ส
nasmjf เพื่อจัดระเบียบความเข้าใจของตนเอง
- macro
NEXT คือ flow หลักที่ใช้ขยับจาก word หนึ่งไปยัง word ถัดไปหลังการรัน
%macro NEXT 0
lodsd ; NEXT: Load from memory into eax, inc esi to point to next word.
jmp [eax] ; Jump to whatever code we're now pointing at.
%endmacro
lodsd จะย้าย double word จาก memory ไปยัง eax และอัปเดตให้ชี้ไปยังตำแหน่งถัดไป
jmp [eax] จะย้ายการรันไปยังตำแหน่งที่กำลังชี้อยู่ และกลายเป็น inner interpreter ของ subroutine นั้น
- ใน Forth แบบดั้งเดิม โดยพื้นฐานจะมีทั้ง code word และ colon word
- code word คือ primitive ที่เขียนด้วย machine code
- colon word คือ word ทั่วไปที่เขียนด้วยภาษา Forth และประกอบขึ้นโดยคอมไพเลอร์
:
- colon word ลงท้ายด้วย
EXIT และ EXIT จะจัดการ return stack ก่อนส่ง flow ต่อไปยัง NEXT
- Forth เป็นโครงสร้างที่ชิ้นส่วนเล็กมาก ๆ ทำงานร่วมกันจนกลายเป็นระบบที่กำลังรันอยู่
- ในระดับล่างจะได้ความยืดหยุ่นและความเรียบง่าย แต่ในระดับสูงอาจต้องแลกด้วยความเข้าใจที่ง่ายน้อยลง
code word, colon word และ compiler ทำงานอยู่บน interpreter ตัวเดียวกัน
SWAP, DUP, DROP แสดงให้เห็นว่า Forth primitive สามารถถูกอิมพลีเมนต์ให้ตรงกับ machine code ได้มากเพียงใด
DEFCODE "SWAP",SWAP,0
pop eax
pop ebx
push eax
push ebx
NEXT
DEFCODE "DUP",DUP,0
mov eax, [esp]
push eax
NEXT
DEFCODE "DROP",DROP,0
pop eax
NEXT
- JonesForth ใช้ i386 call/return stack เป็น Forth parameter stack จึงอิมพลีเมนต์ stack operation ด้วย
pop และ push แบบ native
nasmjf มี code word อยู่ 130 ตัว ซึ่งส่วนใหญ่มีไว้เพื่อประสิทธิภาพ
- มีค่าต่ำสุดในทางทฤษฎีของจำนวน machine-code word ที่จำเป็นสำหรับ Forth system แบบ bootstrappable
- หากลดจำนวน primitive มากเกินไป Forth code ที่เหลืออาจไม่มีประสิทธิภาพและบิดเบี้ยวเกินไป
- งานของ Frank Sergeant A 3-INSTRUCTION FORTH FOR EMBEDDED SYSTEMS WORK กล่าวถึง Forth แบบ 3-instruction บน Motorola MC68HC11 ที่ต้องใช้เพียง 66 bytes
- sectorforth คือ Forth สำหรับ x86 แบบ 16-bit ที่อยู่ใน boot sector ขนาด 512-byte
- colon word คือวิธีสร้าง word ใหม่จากการประกอบ word ที่มีอยู่แล้ว
: SDD SWAP DROP DUP ;
SDD ให้ผลเหมือนกับการเรียก SWAP DROP DUP ตามลำดับ
- ในมุมมองของ indirect threaded code, colon word คือสถานะที่ถูก compile เป็น inner interpreter address ของ code word ทั้งสามตัว
: และ ; ดูเหมือน syntax แต่จริง ๆ แล้วเป็น Forth word
: จะรับชื่อของ word ใหม่และเปิด compile mode
; จะทำ dictionary entry ใหม่ให้เสร็จสมบูรณ์และปิด compile mode
- ผู้ใช้สามารถแทนที่
: เองด้วย definition ของตนเพื่อขยายหรือเปลี่ยน Forth ได้
- syntax เพียงอย่างเดียวของ Forth คือ whitespace ระหว่าง input token
- ใน Forth การ compile คือการใส่ word address หรือตัว literal พร้อม push code ลงใน memory
- ใน normal mode จะรัน word ทันที
- ใน compile mode จะเก็บ word address ลงใน memory
- interpreter ตัวเดียวกันทำทั้งการรัน code และการ compile code
- control structure อย่าง
IF...THEN ก็สามารถอิมพลีเมนต์ด้วย Forth เองได้
: IF IMMEDIATE ' 0BRANCH , HERE @ 0 , ;
: THEN IMMEDIATE DUP HERE @ SWAP - SWAP ! ;
- แม้องค์ประกอบพื้นฐานอย่าง
IF ก็ยังถูกนิยามอยู่ภายในภาษาเอง นี่จึงเป็นเหตุผลสำคัญของชื่อ “The programming language that writes itself”
- nested comment แบบ
( ... ) ก็ถูกอิมพลีเมนต์ด้วย Forth ใน jonesforth.f
- แม้แต่ comment เองก็ยังถูกอิมพลีเมนต์อยู่ภายในภาษา และผู้ใช้สามารถนิยามใหม่หรือเพิ่มรูปแบบ comment ของตนเองได้
- ตัวอย่างนี้เน้นให้เห็นว่า Forth แทบไม่มี native syntax เลย
Dictionary และการนิยามทับทำให้เกิดความขยายได้
- โดยดั้งเดิมแล้ว Forth dictionary ใช้ linked list และการจับคู่คำจะเริ่มจาก entry ล่าสุด
- definition ล่าสุดของคำชื่อเดียวกันจะบัง definition ก่อนหน้า
- สามารถนิยามทับคำใดก็ได้ และแม้แต่คำที่นิยามครั้งแรกด้วย assembly ก็ยังนิยามทับได้
- word ที่ถูก compile ไปแล้วจะเก็บ address ไม่ใช่ชื่อ จึงยังคงชี้ไปยัง address ของ word ก่อนการนิยามทับ
- สามารถเรียกคำก่อนหน้าที่ชื่อเดียวกันจาก definition ใหม่เพื่อขยายความสามารถของคำได้
- เมื่อต้องสร้าง recursive word,
: จะซ่อนหรือทำเครื่องหมายให้ word ที่กำลัง compile อยู่ไม่พร้อมใช้งานใน dictionary
- หากต้องการเรียกตัวเองจากภายใน word ปัจจุบัน ต้องใช้
RECURSE
- ตัวอย่างตัวแปรแอปเปิลที่ดัดแปลงมาจาก Thinking Forth ของ Leo Brodie แสดงให้เห็นความยืดหยุ่นของ Forth
VARIABLE APPLES จะสร้าง word APPLES ที่เมื่อเรียกแล้วจะวาง memory address ลงบน stack
20 APPLES ! จะเก็บค่า 20 ลงใน address นั้น
APPLES ? จะดึงค่าออกมาและแสดงผล
- Thinking Forth (PDF) เปิดให้อ่านฟรี
- แม้ต้องติดตามแอปเปิลสีแดงและสีเขียวแยกกัน ก็ยังไม่จำเป็นต้องแก้โค้ดเดิมที่ใช้
APPLES
VARIABLE COLOR
VARIABLE REDS
: RED REDS COLOR ! ;
VARIABLE GREENS
: GREEN GREENS COLOR ! ;
: APPLES COLOR @ ;
APPLES ตัวใหม่ก็ยังเป็น word ที่วาง address ลงบน stack ดังนั้นรูปแบบการใช้ APPLES ! และ APPLES ? เดิมจึงยังคงเดิม
- มีเพียง address เท่านั้นที่เปลี่ยนไปเป็น
REDS หรือ GREENS ตามสีแอปเปิลที่กำลังใช้งาน
- ในมุมมองของภาษาทั่วไป สิ่งนี้อาจดูเหมือนตัวแปรถูกเปลี่ยนเป็นฟังก์ชัน แต่ใน Forth ทั้งตัวแปรก็เป็น word ที่วาง address และฟังก์ชันก็เป็น word เช่นกัน จึงไม่มีการเปลี่ยนระดับแนวคิดของภาษา
- token ที่ดูเหมือนตัวเลขก็สามารถนิยามใหม่เป็น dictionary word ได้
: 4 12 ;
- เมื่อรัน
." The value of 4 is " 4 . CR จะได้ผลลัพธ์ The value of 4 is 12
Meow5 และ Forth ในฐานะ “เส้นทางที่มีแรงต้านน้อยที่สุด”
nasmjf ซึ่งเป็นการพอร์ต JonesForth ไปยัง NASM ไม่ใช่การจำลองกระบวนการของ Moore แต่เป็นการฝึกแบบ “master copy” ที่เฝ้าสังเกตผลลัพธ์สุดท้ายอย่างละเอียดมากกว่า
- หลังจากนั้น ผู้เขียนได้ทำการทดลอง programming แบบ concatenative สุดขั้วชื่อ
Meow5
- Meow5 เป็นการทดลองที่ต่อโค้ดทุกอย่างเข้าด้วยกันและ inline ตลอดเวลา
- มันเป็น concatenative เพราะใช้แนวคิด parameter stack แบบเดียวกับ Forth
- เป็นการทดลองทางความคิดที่ผลักไปจนสุดว่า ถ้าแทนที่จะเก็บ function call address เราเก็บสำเนาของฟังก์ชันทั้งหมดจะเป็นอย่างไร
- หัวใจของ Meow5 คือการทำทุก word ให้เป็น 100% inline
- แนวคิดนี้เริ่มจาก inline expansion ซึ่งเป็นการปรับแต่งประสิทธิภาพทั่วไปเพื่อหลีกเลี่ยง overhead ของการเรียกฟังก์ชันขนาดเล็ก
- การเรียก primitive ที่มีเพียงคำสั่งเดียวอย่าง
DROP ผ่านการกระโดดหลายครั้งดูเป็นความสิ้นเปลือง
- Meow5 จบลงแบบ “ความล้มเหลวเล็ก ๆ ที่น่ารื่นรมย์”
- ตัวการ inline machine code เองทำงานได้ดี และไฟล์ปฏิบัติการ ELF ที่ส่งออกมาก็ทำงานตามที่ตั้งใจ
- ปัญหาอยู่ที่ข้อมูลสตริง เพราะต้องคัดลอกสตริงทุกครั้ง หรือไม่ก็ต้องติดตามอย่างซับซ้อนว่า word ไหนใช้สตริงใด
INLINE word ของ Forth ที่เปิดให้ inline แบบเลือกได้จึงถูกมองว่าเป็นวิธีที่ดีกว่า
- ในเรื่อง syntax ของสตริงก็เป็นการยืนยันคำแนะนำของ Moore อีกครั้ง
- ใน Forth ใช้ word ชื่อ
" ดังนั้นจึงต้องมีช่องว่างแบบ " Hello World."
- Meow5 เลือกรูปแบบ quoting ที่เป็นธรรมชาติกว่าอย่าง
"Hello World." พร้อม escape sequence เช่น \n, \"
- การเลือกนี้ทำให้ต้องมีการจัดการกรณีพิเศษของ
" กระจายอยู่ใน tokenizer และ interpreter หลายจุด ส่งผลให้ความบริสุทธิ์และความเรียบง่ายลดลง
- เมื่อเริ่มเดินตามเส้นทางของ Forth แล้ว ส่วนที่เหลือก็ดูเหมือนจะ “เขียนตัวเอง” ต่อไป
- Forth คือการ bootstrapping, เป็น metaprogramming และสามารถเป็น OS กับ IDE/editor ได้
- สิ่งนี้นำไปสู่ข้อสรุปว่า หากคุณกำลังสร้าง interpreter ที่ง่ายที่สุดสำหรับ CPU architecture แบบใหม่ทั้งหมด คุณอาจลงเอยด้วยสิ่งที่คล้าย Forth
การทำ Forth ขนาดเล็กและการใช้งานจริง
- Forth สามารถนิยาม Forth เพิ่มเติมได้จากภายใน Forth เอง และ Forth หลายตัวก็มี assembler รวมมาด้วย
- ตอนท้ายของ JonesForth มี stub ของ assembler ที่ทำงานอยู่ใน Forth
;CODE จะอัปเดต header เพื่อให้ codeword ชี้ไปยัง assembled code แทน DOCOL
- PlanckForth เป็นไบนารี Forth ที่เขียนด้วยมือและมีขนาดต่ำกว่า 1KB
- ทั้งไบนารี ELF ที่สมบูรณ์และ Forth implementation ที่ใช้งานได้จริงอยู่ในขนาดต่ำกว่า 1KB
bootstrap.fs เริ่มต้นจากโอเปอเรเตอร์ที่เข้าใจยากในช่วงแรก แล้วอีกไม่กี่ร้อยบรรทัดต่อมากลายเป็น Forth ที่อ่านง่าย
- ตัวอย่าง implementation ขนาดเล็กแสดงให้เห็นความกะทัดรัดอย่างสุดขั้วของ Forth
- SmithForth เป็น machine code Forth ที่ David Smith เขียนด้วยมือ และถูกแนะนำว่าเป็นระบบ Forth ขนาด 1,000 ไบต์และ 1,000 บรรทัด
- sectorforth เป็น boot sector Forth ขนาด 512 ไบต์
- Forth ถูกใช้ในโรงไฟฟ้า หุ่นยนต์ ระบบติดตามขีปนาวุธ ระบบอัตโนมัติในอุตสาหกรรม ภาษาฝังตัวในวิดีโอเกม ฐานข้อมูล งานบัญชี โปรแกรมประมวลผลคำ กราฟิก ระบบคำนวณ Open Firmware boot loader และบนโปรเซสเซอร์กับไมโครคอนโทรลเลอร์หลากหลายชนิด
- Open Firmware เป็นกรณีสำคัญที่มาจากงานวิศวกรรมของ Sun Microsystems
- เพราะมีพื้นฐานเป็น interactive programming language จึงสามารถทดสอบและ bring-up ฮาร์ดแวร์ใหม่ได้อย่างมีประสิทธิภาพ
- ในกรณีของ Space Shuttle ESN นั้น Open Firmware ถูกกล่าวถึงว่าเป็นเครื่องมือที่ใช้ดีบักได้ทั้งฮาร์ดแวร์ ซอฟต์แวร์ ไดรเวอร์แบบปลั๊กอิน และแม้แต่เฟิร์มแวร์เอง
- Jupiter Ace เป็นคอมพิวเตอร์ใช้งานในบ้านของสหราชอาณาจักรในปี 1982 และใช้ Forth เป็นระบบปฏิบัติการ
- ทั้ง OS และ routine library อยู่ใน ROM ขนาด 8KB
- มีคำกล่าวอ้างจากปี 1982 ว่า Forth ที่มีมาในตัว “เร็วกว่า” interpreted BASIC ถึง “10 เท่า” และใช้หน่วยความจำน้อยกว่าครึ่ง
- Canon Cat ในปี 1987 ใช้ Forth เป็นระบบปฏิบัติการ และบรรจุทั้ง OS ชุดโปรแกรมออฟฟิศ และสภาพแวดล้อมการเขียนโปรแกรมไว้ใน ROM ขนาด 256KB
- เป็นผลิตภัณฑ์ที่ทำให้แนวคิดการออกแบบและอินเทอร์เฟซที่ยึดคีย์บอร์ดเป็นศูนย์กลางของ Jef Raskin กลายเป็นจริงทั้งในฮาร์ดแวร์และซอฟต์แวร์
- ขั้นตอนการเข้าใช้อินเทอร์เฟซ Forth อาจไม่ได้ดูเหมือนเป็นเส้นทางการใช้งานหลักที่สุด แต่ถ้ารู้วิธีก็ทำได้ด้วยการกดปุ่มเพียงไม่กี่ครั้ง
ซอฟต์แวร์อวกาศและ Forth
- หนึ่งในการใช้งาน Forth ที่น่าสนใจคือ การสำรวจอวกาศ
- ยานอวกาศมีต้นทุนสูงและเข้าถึงเพื่อซ่อมแซมได้ยากหรือแทบเป็นไปไม่ได้ จึงทำให้ความน่าเชื่อถือของซอฟต์แวร์มีความสำคัญ
- รายชื่อโครงการของ NASA ที่ใช้ Forth มีอยู่ยาวมาก แม้ลิงก์ต้นฉบับจะหายไปแล้ว แต่ยังมีสำเนาใน Wayback Machine และ forth.com
- Space Shuttle Small Payload Accommodations Interface Module (SPAIM) เป็นตัวอย่างของการใช้ Forth
- ทีมพัฒนาจะเขียน routine ของ Forth บน PC ดาวน์โหลดลงไป แล้วทดสอบแบบอินเทอร์แอ็กทีฟ
- มีคำกล่าวอ้างว่าระหว่างภารกิจ Shuttle STS-45 ซอฟต์แวร์การบินของ SPAIM ทำงานได้โดยไม่มีปัญหา
- ระบบ Forth ของ SPAIM รองรับ multitasking โดยแต่ละ task มี stack ของตัวเอง และมี watchdog task คอยเฝ้าดูสถานะของ stack
- Space Shuttle Robot Arm Simulator เป็นกรณีของอุปกรณ์ซับซ้อนที่โปรแกรมเมอร์เพียงคนเดียวพัฒนาเสร็จภายใน 5 สัปดาห์
- ต้องรับคำสั่งจาก joystick แบบ 3 แกนเพื่อควบคุมแขนยาว 50 ฟุตที่มี 6 ข้อต่อและ 6 ระบบพิกัด
- มีการอ้างว่าระบบนี้มี process แยกกัน 14 ตัว
- มีคำกล่าวอ้างว่าการทดสอบ simulation เข้มข้นมากจนหลังติดตั้งที่หน้างานแล้วไม่ได้เปลี่ยนอัลกอริทึม executive control เลย
- Shuttle Mission Design and Operations System (SMDOS) เป็นซอฟต์แวร์ควบคุมภาคพื้นของ JPL
- ระหว่างภารกิจ SIR-B มีการรับมือความขัดข้องของฮาร์ดแวร์หลายอย่างที่หน้างานด้วยการแก้ซอฟต์แวร์
- เนื่องจากปัญหาเสาอากาศและการเปลี่ยนวงโคจร จึงต้องมีแผนการเก็บข้อมูลแบบใหม่ และ SMDOS ถูกใช้เพื่อแสดงแผนที่เหมาะกับเงื่อนไขใหม่
- แม้จะสูญเสียข้อมูลไปมาก แต่ก็สามารถกู้คืนข้อมูลได้ 20% ด้วยวิธีหมุน-บันทึก-หมุน-ส่ง
- Harris RTX2010 เป็นฮาร์ดแวร์ Forth ที่ถูกใช้ในงานอวกาศจำนวนมาก
- รัน Forth ได้โดยตรง
- มี hardware stack 2 ชุดที่ลึก 256 word
- มี clock 8MHz และ latency ต่ำ
- มีคุณสมบัติ radiation-hardened
- Rosetta และ Philae ถูกแนะนำว่าเป็นภารกิจแรกที่ส่งยานไปโคจรรอบดาวหางและนำยานลงจอดลงบนพื้นผิวดาวหาง
- Ion and Electron Sensor ของ Rosetta ใช้ Harris RTX2010
- ยานลงจอด Philae ใช้ RTX2010 จำนวน 2 ตัวใน CDMS และอีก 2 ตัวสำหรับควบคุม ADS
- Rosetta เดินทางตั้งแต่ปี 2004 ถึง 2014 ก่อนจะไปพบกับ 67P/Churyumov-Gerasimenko
- 67P มีความกว้าง 4 กม. และโคจรรอบดวงอาทิตย์ทุก ๆ 6 ปีครึ่ง
- Philae ประสบกับการกระดอนในแรงโน้มถ่วงต่ำบนพื้นผิวเพราะฉมวกและ thruster สำหรับลงจอดล้มเหลว แต่ก็ยังทนทานพอจะทำภารกิจวิทยาศาสตร์ได้ “80%”
- ยังมีกรณีแพตช์โค้ดของ magnetometer บน Galileo ในปี 1993 ด้วย
- magnetometer มี RCA1802, RAM 2KB และ ROM 2KB และเขียนโปรแกรม Forth ผ่านระบบพัฒนาที่ใช้ Apple II
- มีไบต์หน่วยความจำเสียเกิดขึ้นกลางโค้ดของอุปกรณ์ จึงต้องแพตช์เพื่อไม่ให้ใช้ไบต์นั้น
- ผู้ถูกอ้างอิงระบุว่าได้เขียนทั้งสภาพแวดล้อมพัฒนา Forth สำหรับอุปกรณ์นั้นและ hardware simulator ขึ้นใหม่ทั้งหมดด้วย Lisp เพื่อสร้างแพตช์ และใช้เวลาน้อยกว่า 3 เดือนแบบพาร์ตไทม์
Forth ใกล้เคียงกับแนวคิดและสายสืบทอดมากกว่าการมี implementation เดียว
- Forth ใกล้เคียงกับการเป็นแนวคิดที่มี ชุดแนวคิดร่วมและสายสืบทอด มากกว่าจะเป็น implementation ตัวแทนเพียงตัวเดียว
- เหตุผลหนึ่งที่ทำให้ Forth เรียนรู้ได้ยากคือไม่มี implementation เดียวที่เป็นตัวแทนชื่อ “Forth” แบบผูกขาด
- Forth ยุคแรกบางตัวมีมาก่อนชื่อ “Forth” เสียอีก
- มาตรฐานของ Forth สืบต่อมาในเอกสาร ANS Forth โดยมีการกล่าวถึง Forth 2012 Standard และคณะกรรมการ Forth200x
- Forth หลายตัวมีแนวคิดและ word ร่วมกัน แต่ Forth ที่ออกแบบเฉพาะทางก็มีคำศัพท์เฉพาะของตนเอง
- Chuck Moore ก่อตั้ง Forth, Inc ในปี 1973 และหลังจากนั้นก็พอร์ต Forth ไปยังหลายระบบ พร้อมทั้งยังสร้างระบบใหม่ ๆ อย่างต่อเนื่อง
- colorForth เป็นสภาพแวดล้อมยุคหลังของ Chuck Moore
- สีในซอร์สโค้ดเข้ามาแทนที่เครื่องหมายวรรคตอนบางส่วนของ Forth มาตรฐานเพื่อกำหนดวิธีประมวลผล word
- มีการกล่าวว่าสีช่วยทำให้ semantics ของ Forth เรียบง่ายขึ้น เพิ่มความเร็วในการ compile และยังช่วยเรื่องสายตาที่ไม่ดีของ Moore ด้วย
- colorForth มีระบบปฏิบัติการของตัวเองขนาด 63KB รวมอยู่ด้วย
- Moore มองว่าเมื่อมีการเพิ่มความสามารถเข้ามาเรื่อย ๆ ซอฟต์แวร์ก็จะซับซ้อนขึ้น และสุดท้ายจะกลายเป็นสิ่งที่ไม่มีใครกล้าเปลี่ยนเพราะกลัวผลลัพธ์ที่ไม่ได้ตั้งใจ
- สิ่งที่จำเป็นตามมุมมองนี้คือโปรแกรมเมอร์ที่ทุ่มอาชีพให้กับแอปพลิเคชันเดียว คอยเขียนมันขึ้นใหม่ซ้ำ ๆ จนสมบูรณ์แบบ
ความเป็นมิตรกับเครื่องจักร, ชิป Forth, GreenArrays
- Chuck Moore ต่อต้านความซับซ้อนของซอฟต์แวร์มาตั้งแต่ทศวรรษ 1950 และมีการยกคำพูดที่มองว่าระบบปฏิบัติการอย่าง Windows, UNIX, DOS เป็นสิ่งที่เข้าใจไม่ได้หรือไม่จำเป็น
- ผู้เขียนอธิบายปรัชญาของ Moore ด้วยแนวคิด Mechanical Sympathy
- คำนี้มาจากคำพูดของนักขับ Formula One อย่าง Jackie Stewart และในบริบทซอฟต์แวร์ถูกใช้ใน Why Mechanical Sympathy? ของ Martin Thompson
- Forth มักได้รับความนิยมในหมู่ “คนฮาร์ดแวร์” เช่น วิศวกรไฟฟ้าและผู้ออกแบบระบบฝังตัว
- ดูเหมือนว่าความหลงใหลที่แท้จริงของ Chuck Moore จะอยู่ที่การออกแบบโปรเซสเซอร์
- Harris RTX2000 และ RTX2010 ถูกแนะนำว่าโดยพื้นฐานแล้วเป็นชิปของ Moore
- Moore ออกแบบฮาร์ดแวร์มาตั้งแต่ Novix N400 gate array ในปี 1983 และแบบที่ได้รับการปรับปรุงถูกขายให้ Harris จนกลายเป็นชิป RTX
- Moore ออกแบบโปรเซสเซอร์ด้วย OKAD ซึ่งเป็นซอฟต์แวร์ VLSI ของตัวเองที่เขียนด้วย Forth 500 บรรทัด
- VLSI Design Tools (OKAD) อธิบายว่ามันให้ทุกอย่างที่จำเป็นต่อการออกแบบชิปด้วย colorForth 500 บรรทัด
- OKAD เป็นชุดเครื่องมือที่รวมเทคโนโลยีลอจิกเกต, การจัดวางวงจร, simulation การทำงานทางไฟฟ้า, และการ export GDSII
- Novix NC4000 เป็นเอนจินประมวลผลความเร็วสูงมากที่ออกแบบมาเพื่อรันคำสั่ง Forth ระดับสูงโดยตรง
- มันได้ประสิทธิภาพจากการตัด assembly language ทั่วไปและ internal microcode ออกไป
- สถาปัตยกรรม dual stack ลด overhead ของการทำ subroutine ได้อย่างมาก
- ชิป GreenArrays ถูกแนะนำโดยเน้นจากงานนำเสนอปี 2013 ของ Moore เรื่อง “Programming a 144-computer chip to minimize power”
- มีคอมพิวเตอร์แบบ asynchronous 144 ตัวอยู่ในชิปเดียว
- core ที่ว่างงานใช้พลังงาน 100 nW, core ที่ทำงานใช้ 4 mW และรันที่ 666 Mips ก่อนกลับสู่สถานะว่างงาน
- เมื่อคอมพิวเตอร์ทุกตัวทำงานที่ความเร็วสูงสุด การใช้พลังงานอยู่ที่ 550 mW หรือประมาณ 0.5 W
- เอกสาร GreenArrays Architecture เน้นคำว่า “NO CLOCKS”
- มีคำอธิบายว่าการสร้างและกระจาย clock ของคอมพิวเตอร์ทั่วไปใช้พลังงานมากแม้ตอนรอ แต่ไม่ได้ทำงานอะไร
- GreenArrays ถูกแนะนำว่าไม่ใช่ Multi-Core CPU แต่เป็น Multi-Computer System
ความเรียบง่าย, ประสิทธิภาพ, และอนาคตของการประมวลผลพลังงานต่ำ
- ผู้เขียนมองว่าทั้งซอฟต์แวร์และฮาร์ดแวร์เดินหน้าต่อไปในทิศทางของการซ้อนทับชั้นความซับซ้อนมากขึ้นเรื่อย ๆ
- การประมวลผลของดาต้าเซ็นเตอร์ขนาดใหญ่ถูกมองว่าราคาถูกหรือฟรี เพราะมีค่าโฆษณาช่วยจ่ายทางอ้อม
- สิ่งที่ผู้ใช้จ่ายจริงคือความสนใจและข้อมูลส่วนตัวของตน
- ผู้เขียนโต้แย้งว่าไม่มีเหตุผลที่จะต้องใช้ซอฟต์แวร์ที่ไร้ประสิทธิภาพและถูกสร้างอย่างหละหลวมมากขึ้นเรื่อย ๆ พร้อมกับความต้องการฮาร์ดแวร์ที่สูงชันขึ้นต่อไป
- ภาษาแนว Forth อาจมีอนาคตที่แข็งแกร่งในด้านต่อไปนี้
- คอมพิวเตอร์ขนาดเล็กที่มีอยู่ทุกหนแห่ง
- พลังงานแสงอาทิตย์
- VM ที่มีข้อจำกัดอย่างมาก
- Dennard scaling แทบหยุดลงราวปี 2006
- ความสัมพันธ์ที่ทรานซิสเตอร์ขนาดเล็กลงทำให้ได้ความเร็วสูงขึ้นและแรงดันต่ำลงไปถึงจุดชะงักที่ราว 4GHz เพราะกระแสรั่วและความร้อน
- The Free Lunch Is Over ของ Herb Sutter เป็นบทความที่ว่าด้วยการที่แนวทางการเพิ่มประสิทธิภาพ CPU กำลังเปลี่ยนไปสู่ hyper-threading และ multicore
- Sutter มองว่าต้องออกแบบแอปพลิเคชันใหม่ให้เหมาะกับการทำงานพร้อมกัน หรือไม่ก็เขียนโค้ดที่มีประสิทธิภาพและสิ้นเปลืองน้อยกว่า
- เขากล่าวว่าการปรับแต่งประสิทธิภาพไม่ได้สำคัญน้อยลง แต่จะยิ่งสำคัญขึ้น
- ทุกวันนี้เราสามารถซื้อ microcontroller ที่ทรงพลังยิ่งกว่า IBM 704 มากได้ในราคาเพียงไม่กี่เหรียญ และเขียน Forth system ที่ทรงพลังบนมันได้
- microcontroller สามารถทำงานด้วยแบตเตอรี่ coin cell หรือแผงโซลาร์เซลล์ขนาดเล็ก
- จากนั้นผู้เขียนกล่าวต่อว่าไม่เคยมีช่วงเวลาใดที่น่าทึ่งสำหรับการประมวลผลขนาดเล็กเท่านี้มาก่อน
- หากต้องการเข้าใจ Forth ต้องพิจารณาความแตกต่างระหว่าง “simple” และ “easy”
- Simple Made Easy ของ Rich Hickey ถูกแนะนำว่าเป็นงานบรรยายที่ทำให้สามารถพูดถึงความแตกต่างนี้ได้
- Forth ไม่ใช่สิ่งที่ง่าย และอาจไม่สนุกเสมอไป แต่เป็นภาษาที่เรียบง่ายอย่างแน่นอน
- Growing a Language ของ Guy Steele เป็นงานบรรยายที่แสดงให้เห็นว่าภาษาถูกสร้างขึ้นจาก primitive ได้อย่างไร
- คำกล่าวเกี่ยวกับ Lisp ที่ว่า เมื่อคำใหม่ที่ผู้ใช้กำหนดดูเหมือน primitive และ primitive เองก็ดูเหมือนคำที่ผู้ใช้กำหนด เมื่อนั้นภาษาที่ใหญ่ขึ้นอย่างไร้รอยต่อก็เกิดขึ้น สามารถนำมาใช้กับ Forth ได้เช่นกัน
- ข้อเชิญชวนสุดท้ายคือให้สร้างภาษาการเขียนโปรแกรมที่สมบูรณ์แบบสำหรับตัวเอง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ตั้งใจให้ใช้กับ Blue Pill และ Arduino รุ่นดั้งเดิม แต่พัฒนาเป็นครอสคอมไพเลอร์เพื่อให้ทดสอบบนโฮสต์ได้
อินมากจนเฝ้ารอเวลาหลังเลิกงานในแต่ละวันเพื่อมานั่งเล่นกับมัน จบงานได้ภายในเย็นวันธรรมดา 5 วันกับสุดสัปดาห์อีก 1 วัน และการสร้าง Forth ก็สนุกมากขนาดนั้น
ขอแนะนำอย่างยิ่ง และครั้งเดียวที่เคยได้ความรู้สึกแบบตาสว่างคล้ายกันก็คือตอนเจอ Lisp macro ครั้งแรก(https://www.thanassis.space/score4.html#lisp)
มันกินเวลาแทบทั้งหมดของเวลาว่างในเทอมนั้นไปหมด และมีวันหนึ่งที่ผมมองนาฬิกาแล้วเพิ่งรู้ว่าตัวเองอดนอนทั้งคืนตอนฟ้าเริ่มสางแล้ว
ผมไม่เคยใช้ Forth แบบจริงจังในชีวิตจริง แต่ประสบการณ์การสร้างมันขึ้นมาจากศูนย์นี่ใกล้เคียงกับคำว่า ประสบการณ์ทางศาสนา มากจนแทบไม่มีคำอื่นจะอธิบายได้
มันเหมือนสิ่งที่ Fred Brooks พูดถึงว่าเป็นแก่นแท้ที่ถูกกลั่นบริสุทธิ์ของการเขียนโปรแกรม: โปรแกรมเมอร์ทำงานอยู่ห่างจากวัตถุดิบของความคิดบริสุทธิ์เพียงนิดเดียว เหมือนกวีสร้างปราสาทกลางอากาศด้วยจินตนาการล้วน ๆ และโปรแกรมคือเวทมนตร์ในโลกจริงที่ทำให้สิ่งซึ่งไม่เคยมีอยู่มาก่อนมีชีวิตขึ้นมาบนหน้าจอ เมื่อใส่คาถาได้ถูกต้อง
งานที่เคยใช้เวลา 19 วินาทีในการพิมพ์ตัวเลข 1000 ตัวบนหน้าจอ กลายเป็นเสร็จแทบจะทันที
และยังได้บทเรียนใหญ่ด้วย คือพอดู machine code ที่สร้างออกมาแล้วคิดว่ามันสมบูรณ์แบบจนปรับปรุงไม่ได้แล้ว แต่พอกลับมาวันถัดไปก็ทำให้เร็วขึ้นได้อีกมาก
ก็ถูกอยู่ระดับหนึ่ง แต่ Forth ไปไกลกว่านั้นตรงที่สามารถนิยาม word ใหม่ให้กลายเป็นส่วนหนึ่งของตัวภาษาได้เลย
word เหล่านี้ใช้ได้เหมือนโอเปอเรชันที่มีมาในตัว และถึงขั้นเปลี่ยนวิธีการทำงานของภาษาได้ด้วย
เพราะมันเป็นภาษาที่ขยายได้ คุณจึงสร้าง word สำหรับนิยามโครงสร้างควบคุมใหม่หรือแม้แต่เปลี่ยนไวยากรณ์ได้ และความยืดหยุ่นแบบนี้ก็หาได้ไม่บ่อยในภาษาอื่น
ในแง่นี้ Forth จึงมองได้ว่าเป็นภาษาที่ “เขียนตัวเองได้” เพราะมันเปิดให้โปรแกรมเมอร์ปรับแต่งและขยายภาษาได้ในระดับที่ลึกมาก
มันยังคล้ายกับระบบ macro ของ Lisp ด้วย เพราะเช่นเดียวกับที่ Lisp macro เปิดให้สร้างโครงสร้างไวยากรณ์ใหม่และภาษาจำเพาะโดเมนผ่านการแปลงตอนคอมไพล์ word ของ Forth ก็เปิดให้ขยายทั้งไวยากรณ์และความสามารถของภาษาได้
อาจมีบางกรณีอย่างการคูณเมทริกซ์ที่การเขียน
A = B + C * D;ดีกว่าการต้องระบุฟังก์ชันที่จะเรียกทีละตัว แต่ผมไม่เคยเจอปัญหาแบบนั้นจริง ๆเลยสงสัยว่าผมจินตนาการไม่พอเอง หรือว่านี่มีประโยชน์เฉพาะบางโดเมนซึ่งผมไม่เคยอยู่ในโดเมนนั้น หรือว่าไวยากรณ์ของ Forth มันเรียบจนต้องขยายถึงจะใช้งานได้ดี หรือจริง ๆ แล้วคนแค่อยากแต่งภาษาของตัวเองเหมือนแต่งรถ
ผมไม่ค่อยเข้าใจว่าทำไมคนถึงสนใจเรื่องนี้กันจริงจัง
https://duskos.org/
ก็จริงที่คุณจะคาดหวังอะไรได้มากแค่ไหนจากของที่รันบน RAM 8KB แต่ถึงจะมีฟังก์ชันพื้นฐาน มันก็แทบไม่มีทั้งไดรเวอร์และแนวคิดเรื่อง abstraction ส่วนใหญ่ในเชิงประวัติศาสตร์
โค้ดถูกโหลดจากซอร์สจึงช้า และการลิงก์ก็ใกล้เคียงกับการโหลดบล็อกตามลำดับที่ถูกต้องมากกว่า ส่วนถ้าจะโหลดโปรแกรมใหม่ก็ต้องลบโปรแกรมปัจจุบันทิ้งก่อน
จะบอกว่ามันดีกว่า CP/M ที่มัก cold start เครื่องตอนโปรแกรมจบการทำงานมากนักก็คงยาก แต่อย่างน้อย CP/M ก็แยก BIOS กับ BDOS ออกจากกัน
ตั้งใจว่าจะต้องไปดูให้ได้ก่อนสุดสัปดาห์หน้า
ตอนเป็นวัยรุ่นผมสร้างระบบ x86 Forth สำหรับ DOS หลายตัว และตัวสุดท้ายก็กลายเป็น implementation ที่ค่อนข้างขัดเกลาและรองรับ ANS ชื่อ “Third”: https://github.com/benhoyt/third
การที่คุณมีคอมไพเลอร์ Forth แบบ bootstrap ครบชุดพร้อม assembler ได้ด้วยโค้ดแค่ไม่กี่พันบรรทัดนั้นน่าทึ่งมาก
เมื่อไม่นานมานี้ผมยังถอดบทความเก่าที่เคยเขียนร่วมกันลงในนิตยสาร Forth Dimensions ออกมาใหม่ด้วย
ไอเดียของ Forth ยังดีอยู่เสมอ แต่ การจัดการสแตก นั้นน่าเบื่อเร็วมาก และยังอ่านยากมากด้วย
ดูได้จากตัวอย่างโค้ดใน https://benhoyt.com/writings/forth-lookup-tables/ โดยเฉพาะ Search-Table แม้การตั้งชื่อจะยาก แต่ดูเหมือนการไม่ตั้งชื่อจะยากยิ่งกว่า
โค้ดของเขาโดยมากแทบไม่มีการสลับสแตกเลย ตัวอย่าง: http://www.merlintec.com/download/color.html
ตอน bootstrap เห็นมันเรียก
kernel.comเลยสงสัยว่า kernel.com สร้างขึ้นมายังไงhttps://www.youtube.com/watch?v=0PclgBd6_Zs
ว่ากันว่า Forth ขับเคลื่อนคอมพิวเตอร์พลังงานต่ำมากได้แบบนี้: GreenArrays กำลังจัดส่งชิปแบบอะซิงโครนัส 144 คอร์ และใช้พลังงานเพียง 7 pJ/inst
คอร์ที่ว่างอยู่จะไม่ใช้พลังงาน (100 nW) และคอร์ที่ทำงานอยู่จะรันอย่างรวดเร็วที่ 4 mW (666 Mips) ก่อนจะกลับสู่สถานะว่างระหว่างรอการสื่อสาร
--Chuck Moore
https://youtu.be/0PclgBd6_Zs?t=389
มีภาพประกอบที่น่าดึงดูดที่สุดภาพหนึ่งเท่าที่เคยเห็นในตำราเรียน
[0] https://www.forth.com/starting-forth/
[0] https://www.dnd.utwente.nl/~tim/colorforth/Leo-Brodie/thinki...
ผมเลยทำ Forth/2 ขึ้นมาเพื่อต่อต้านคำพูดนั้น
มันเป็นคอมไพเลอร์ Forth แบบ native code สำหรับ OS/2 ที่ใช้ direct-threaded ซึ่งเขียนด้วยแอสเซมบลี และ Brian Matthewson ก็ช่วยเขียนคู่มือที่ยอดเยี่ยมให้ จนมีผู้ใช้หลายสิบคน
[1] https://sourceforge.net/projects/forth2/
โดยพื้นฐานแล้วเหมือนกับบทความตอนนี้ แต่มีข้อความน้อยกว่ามากและมีช่องโหว่มากกว่า
ที่พูดถึงเพราะมันยังแสดงให้เห็นถึงความงามของความมินิมัลในแง่ของ เทคโนโลยีเว็บไซต์ ที่ใช้รองรับด้วย
[0] http://ratfactor.com/forth/forth_talk_2023.html
[1] http://ratfactor.com/minslides/
วิธีใช้งานยังค่อนข้างไม่ชัดเจน[2] แต่ก่อนหน้านี้ก็เคยถูกพูดถึงที่นี่มาแล้ว[3] และตัว implementation ก็ดูแข็งแรงดี
มันไม่ใช่ REPL Forth virtual machine แต่ก็เป็น การนำไปใช้เป็น virtual machine ที่น่าประทับใจ
ถ้า FORTH คือ virtual machine ผมก็คิดมาตลอดว่าเมื่อคุณต้องการระบบเล็ก ๆ ที่มีประสิทธิภาพสำหรับจัดการข้อมูลแบบสตรีมมิง มันอาจเป็นตัวเลือกที่เหมาะที่สุดซึ่งให้ประสิทธิภาพใกล้เคียง bare metal ได้
และยังไม่ต้องไปปวดหัวกับระบบปฏิบัติการด้วย
มันเหมือนกับการทำสิ่งที่ FPGA ทำอยู่บน CPU มาตรฐานโดยเนื้อแท้หรือเปล่าก็ไม่แน่ใจ
แต่ผมกำลังนึกภาพมันเป็นระบบเฉพาะทางที่ไม่จำเป็นต้องเขียนไดรเวอร์ทุกตัวเองเพื่อเชื่อมต่อกับฮาร์ดแวร์ที่ต้องใช้
[1] https://docs.rs/rust-forth-compiler/latest/src/rust_forth_co...
[2] https://docs.rs/fortraith/latest/fortraith/
[3] https://news.ycombinator.com/item?id=23501474
จุดประสงค์ไม่ใช่เพื่อคัดลอกไอเดียต้นฉบับแบบตรงตัว แต่มันทำงานแตกต่างออกไปเล็กน้อย
ในบทความบอกว่าสามารถพบ Forth ได้ ก็เลยขอทิ้ง implementation ของผมไว้ด้วย: https://github.com/loscoala/goforth
ความแตกต่างที่ใหญ่ที่สุดคือ ใน Forth แบบแปรผันตัวนี้ ข้อความซอร์สจะถูกแปลงเป็น ไบต์โค้ด ทั้งหมด และไม่มี runtime ในความหมายแบบ Forth ดั้งเดิม
เลยแปลงไบต์โค้ดเป็น C ได้ง่าย
ผมใช้ Forth ตัวนี้สร้างโค้ด C แล้วเอาโค้ดนั้นไปฝังในซอฟต์แวร์อื่นเพื่อใช้งาน
มีโปรเจกต์โอเพนซอร์สที่ดีมากตัวหนึ่งซึ่งช่วยฝึกการฟังโน้ตและการอ่านโน้ตฉับพลันได้ เขียนด้วยภาษาที่ผู้เขียนสร้างขึ้นเอง และภาษานั้นคอมไพล์เป็น JavaScript
ความยุ่งยากในการตั้งค่า toolchain มากเกินไปจนแม้จะรู้ว่ามีบั๊กอยู่หลายจุด ก็ยังไม่กล้าลงมือแก้
https://sightreading.training/
https://github.com/leafo/sightreading.training
โปรเจกต์นี้เขียนด้วยภาษาที่ชื่อว่า ‘Moonscript’: https://github.com/leafo/moonscript
Moonscript คอมไพล์เป็น Lua และ Lua คอมไพล์เป็น JS
บ้าคลั่งมาก เป็นความบ้าคลั่งที่เท่มากก็จริง แต่ก็ยังทำให้ผมไม่ได้กลายเป็นผู้มีส่วนร่วมอยู่ดี