2 điểm bởi GN⁺ 2023-07-18 | 1 bình luận | Chia sẻ qua WhatsApp
  • Forth khởi đầu từ một trình thông dịch nhỏ do Chuck Moore tạo ra để rút ngắn quy trình biên dịch dài dòng và dùng thẻ đục lỗ, rồi phát triển thành một hệ thống hấp thụ cả trình soạn thảo, hệ điều hành và trình biên dịch
  • Ký pháp hậu tố (RPN), stack dữ liệu và word (dictionary) không phải là cú pháp xa lạ, mà là thiết kế nhằm giảm lãng phí và các thao tác lặp lại trên phần cứng nhiều hạn chế
  • Cốt lõi của Forth nằm ở cấu trúc có thể bootstrap, nơi ngay cả các yếu tố như :, ;, IF, chú thích và biến cũng có thể được định nghĩa và định nghĩa lại bên trong chính ngôn ngữ
  • Các implementation như JonesForth, nasmjf, PlanckForth, sectorforth cho thấy Forth có thể bắt đầu từ vài chục đến vài trăm byte, hoặc từ một số ít primitive, rồi mở rộng thành trình thông dịch, trình biên dịch, assembler và DSL
  • Các ví dụ về tàu vũ trụ, Open Firmware, Jupiter Ace, Canon Cat, Harris RTX2010 và GreenArrays cho thấy Forth gắn rất chặt với phát triển tương tác, mã nhỏ gọn, tính thân thiện với phần cứng và điện toán tiêu thụ điện thấp

Điểm khởi đầu từ huyền thoại Usenet đến hành trình khám phá Forth

  • Dave Gauer đã ghi lại hành trình cá nhân khi khám phá Forth và đặt nó trong lịch sử điện toán; trang này được chuyển thể từ một bộ slide thuyết trình ngắn
  • Trong thập niên 1990, các nhóm comp.* trên Usenet, đặc biệt là comp.lang.*, là nơi quan trọng để học và thảo luận về lập trình
    • Thông báo đầu tiên của Linus Torvalds về Linux cũng được nhắc đến như một ví dụ từng xuất hiện trên comp.os.minix vào năm 1991
    • Cuối thập niên 1990, Perl chiếm vai trò lớn trong Web thời kỳ đầu với tư cách là ngôn ngữ xử lý trang động và biểu mẫu thông qua CGI
  • Những huyền thoại bắt gặp từ thời Usenet như các ngôn ngữ họ Lisp, Y combinator, The Little Schemer và The Story of Mel đã dẫn tới sự tò mò về Forth
  • Ban đầu, Forth hiện ra qua câu chuyện về “một ngôn ngữ linh hoạt đến mức có thể thay đổi giá trị của số nguyên”, còn Chuck Moore được nhớ đến như một “phù thủy điên” có thể viết bất kỳ chương trình nào chỉ bằng vài màn hình mã
  • Loạt bài blog programming in the twenty-first century của James Hague trở thành động lực cuối cùng để đi sâu tìm hiểu Forth

RPN và stack chỉ là điểm khởi đầu

  • Ấn tượng đầu tiên về Forth là ký pháp hậu tố, hay Reverse Polish Notation (RPN)
    • Khác với ký pháp trung tố thông thường 3 + 4, Forth đặt toán tử sau toán hạng như 3 4 +
    • Ví dụ Forth 3 4 * 5 6 * + . sẽ in ra 42
    • Trong dc, phép tính tương tự được biểu diễn là 3 4 * 5 6 * + p
  • RPN cho phép tính các biểu thức lồng nhau theo thứ tự mong muốn mà không cần dấu ngoặc
    • 3 4 * tạo ra 12, 5 6 * tạo ra 30, và dấu + cuối cùng tạo ra 42
    • Trong Forth, . lấy một giá trị ra khỏi stack và in nó
  • Máy tính HP-35 là một ví dụ lịch sử quan trọng giúp RPN được biết đến cả bên ngoài khoa học máy tính
    • Đầu thập niên 1970, HP có các máy tính để bàn mạnh mẽ, và HP-35 được giới thiệu như một ví dụ đưa năng lực tính toán đó vào một máy tính bỏ “túi áo”
    • Máy tính HP nổi tiếng với cú pháp RPN; RPN hiệu quả nhưng có vẻ hơi khó hiểu với người ngoài
  • Đặc trưng thứ hai là stack dữ liệu
    • Các thao tác như PUSH, POP, SWAP, DUP cũng là các word trong Forth
    • Khi nhập số, nó được đưa lên stack; toán tử lấy giá trị từ stack để tính toán rồi đưa kết quả trở lại stack
  • Stack làm giảm nhu cầu đặt tên cho giá trị trung gian
    • Trong nhiều imperative language, cần các tên tạm như result2, matched_part3
    • Cách làm việc không cần tên này cũng được gọi là implicit, tacit hoặc point-free programming
    • Hiểu Forth chỉ bằng RPN và stack là chưa đủ, nhưng đây là điểm khởi đầu hợp lý để hiểu nguồn gốc lịch sử của nó

Concatenative programming và Joy, cùng sự khác biệt với Forth

  • Khi tìm hiểu Forth, ta sẽ gặp khái niệm concatenative programming
    • Ví dụ applicative là eat(bake(prove(mix(ingredients))))
    • Ví dụ concatenative là ingredients mix prove bake eat
    • Các hàm được liệt kê theo thứ tự, và giá trị ở mỗi bước được truyền ngầm sang bước tiếp theo
  • Joy là một ví dụ tiêu biểu của concatenative language
    • Manfred von Thun lấy cảm hứng từ bài giảng ACM Turing Award năm 1977 của John Backus, “Can Programming Be Liberated from the von Neumann Style?”
    • Trong Joy, mọi hàm nhận một stack làm đầu vào và trả về một stack làm đầu ra
    • Chương trình là danh sách các hàm được đọc từ trái sang phải
  • Quotation và combinator của Joy cho thấy cách tính toán không cần biến
    • JavaScript [1, 2, 3, 4].map(n => n + 1) tạo ra [2,3,4,5]
    • Trong Joy, có thể nhận cùng kết quả bằng [1 2 3 4] [1 +] map
    • [] của Joy là cơ chế quotation có thể chứa không chỉ dữ liệu mà cả chương trình
  • Combinator được xử lý như hàm bậc cao nhận hàm làm đầu vào
    • map() là ví dụ trừu tượng hóa boilerplate duyệt danh sách
    • Các combinator I, K, S và SKI calculus xuất hiện như những cấu trúc giải thích tính toán phổ quát
    • Chỉ riêng SK cũng có thể tạo thành một hệ thống hoàn chỉnh cho tính toán phổ quát
  • Forth cũng có thể tạo hàm bậc cao bằng execution token và word EXECUTE
    • FOO EXECUTE thực thi word mà word FOO trả về
    • Có thể định nghĩa các combinatorial word như MAP, FOLD, REDUCE
  • Forth và Joy có cú pháp bề ngoài giống nhau, nhưng cách diễn giải biểu thức thì khác
    • Trong Forth, 2 3 + được đọc là “push 2 và 3 lên stack rồi cộng chúng”
    • Trong Joy, nó được đọc là “composition của các hàm 2, 3, + tương đương với hàm 5”
    • Forth gần với một ngôn ngữ trưởng thành trong tương tác với phần cứng hơn là từ các nguyên lý concatenative computing trừu tượng

Con đường Chuck Moore tạo ra Forth

  • Năm 1958, Chuck Moore dùng Fortran và IBM 704 trong thời gian ở Smithsonian Astrophysical Observatory và MIT
    • Trong Forth, the Early years, Moore nói: “Compiling took 30 minutes...you got one shot per day”
    • IBM 704 là một máy tính dùng bóng chân không chiếm cả căn phòng, và đi kèm là trích dẫn rằng trung bình khoảng 8 giờ nó lại hỏng một lần
  • Để giảm việc biên dịch lại, Moore tạo ra một trình thông dịch đơn giản đọc các thẻ điều khiển chương trình
    • Có thể cấu hình các equation khác nhau cho nhiều satellite mà không cần recompile
    • free-form input format đáng tin cậy hơn với con người so với các cột formatted của Fortran
    • Hệ thống này trở thành nguồn gốc của hệ thống về sau được gọi là Forth
  • Năm 1961 tại Stanford, Moore dùng Burroughs B5500 và viết một mathematical application tên là CURVE
    • CURVE có interpreter tinh vi hơn, data stack và control flow operator
    • Các chức năng đại khái tương ứng với các Forth word như IF ELSE DUP DROP SWAP + - *
    • Khi parameter stack và khả năng định nghĩa procedure mới được thêm vào, một cấu trúc gần với Forth xuất hiện
  • Khoảng năm 1965, với sự xuất hiện của teletype, paper tape, timesharing và môi trường interactive terminal, Forth trở nên tương tác hơn
    • Các word như KEY, EMIT, CR, SPACE, DIGIT được thêm vào
    • Những word này biến hệ thống của Moore thành một program editor, cho phép người dùng edit program ngay bên trong program
  • Năm 1968 tại Mohasco, Moore làm việc với IBM 1130 và đặt tên “FORTH”
    • IBM 1130 có cấu hình 16-bit, 8KB RAM, và tên tệp bị giới hạn ở 5 ký tự
    • Hệ thống “fourth generation” của Moore trở thành FORTH vì giới hạn 5 ký tự
    • Vào giai đoạn này, return call stack và word dictionary được thêm vào
  • Word dictionary có tên của Forth hoạt động như abstraction chính
    • : DOUBLE DUP + ;
    • : QUAD DOUBLE DOUBLE ;
    • Nếu không có return stack, sau khi chạy DOUBLE sẽ không thể quay lại vị trí còn lại của QUAD

NRAO, việc port và indirect threaded code

  • Đầu thập niên 1970, Moore viết phần mềm điều khiển máy tính cho radio telescope tại National Radio Astronomy Observatory
    • NRAO có chính sách dùng Fortran trên minicomputer, nhưng nhờ các thành công trước đó, Moore được phép dùng Forth
    • Trong spectral-line observing, hệ thống có thể hiển thị spectra đang được thu thập và fit line-shapes bằng least-squares
    • Công việc này thúc đẩy state-of-the-art của online data reduction, và các nhà thiên văn học dùng nó để phát hiện cũng như map các inter-stellar molecules
  • Elizabeth “Bess” Rather tiếp nhận Forth và viết manual Forth đầu tiên vào năm 1972
    • Sau đó bà đồng sáng lập FORTH, Inc với Chuck Moore
    • Cho đến khi nghỉ hưu năm 2006, bà vẫn là một trong những chuyên gia và promoter quan trọng của Forth language
  • Forth được port sang nhiều máy như IBM 360/50, Honeywell 316, Honeywell DDP-116, DEC PDP-11
    • Bản triển khai Forth cho H316 được lập trình ngay trên chính máy tính đó và được dùng để tạo các Forth khác, nên được xem là complete, stand-alone implementation đầu tiên
    • PDP-11 là một minicomputer quan trọng gắn với lịch sử của Unix và C programming language
  • Nền tảng giúp Forth có thể được port sang nhiều máy là indirect threaded code
    • Ở đây threaded code không liên quan đến concurrency hay multi-threaded programming
    • threaded code lưu danh sách địa chỉ subroutine thay vì instruction gọi subroutine
    • Để chạy address list, cần có code interpreter
  • indirect threaded code lưu danh sách các địa chỉ trỏ tới địa chỉ trỏ tới code, chứ không phải địa chỉ trỏ trực tiếp tới code
    • Nhờ tầng indirection thứ hai, mỗi loại subroutine khác nhau có thể có inner interpreter riêng
    • Trong Forth, outer interpreter là phần người dùng tương tác từ terminal, còn inner interpreter thực thi phần còn lại của word
  • Đến thời điểm này, Forth đã vượt ra khỏi một command interpreter đơn giản và mở rộng thành interactive language, editor, operating system, cùng phương pháp lưu trữ và thực thi code
    • Các đặc tính được định hình gồm postfix notation, stack-oriented, concatenative style, interpreted, highly adaptable với machine architecture, và cực kỳ compact
    • Forth không phải là một ngôn ngữ được thiết kế một lần vào năm 1958, mà là kết quả Moore phát triển theo nhu cầu của mình và phần cứng mới

Muốn hiểu Forth thì phải triển khai Forth

  • Trong lời khuyên “To understand Forth, you have to implement a Forth”, từ quan trọng là a Forth
    • Theo quan điểm của Chuck Moore, Forth system tốt nhất khi được custom-tailored cho system và task
  • Trước khi xử lý mã nguồn JonesForth, tác giả viết Assembly Nights để học các nền tảng về assembly và Linux ABI
    • JonesForth dùng mã nguồn i386 assembly viết bằng GNU GAS assembler
    • Nó chỉ dành cho 32-bit và dùng trực tiếp Linux system call ABI
    • Tác giả mất khoảng 1 năm để port JonesForth sang một bản sao chạy với NASM assembler, và bản port này là nasmjf
  • Trong quá trình port nasmjf, tác giả học được cách vận hành của Forth indirect threaded truyền thống
    • jonesforth.S của JonesForth là một tệp duy nhất chứa phần assembly, và Richard W.M. Jones dùng ASCII art cùng phần giải thích để hướng dẫn luồng interpreter
    • Để hệ thống hóa hiểu biết của mình, tác giả viết nhiều sơ đồ ASCII art trong mã nguồn nasmjf
  • Macro NEXT là luồng cốt lõi chuyển sang word tiếp theo sau khi thực thi một 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 chuyển double word từ memory vào eax và cập nhật để trỏ tới vị trí kế tiếp
  • jmp [eax] chuyển thực thi tới nơi hiện đang được trỏ tới, trở thành inner interpreter của subroutine đó
  • Forth truyền thống về cơ bản có code word và colon word
    • code word là primitive viết bằng machine code
    • colon word là word thông thường viết bằng Forth language và được lắp ráp bằng compiler :
    • colon word kết thúc bằng EXIT, và EXIT xử lý return stack rồi tiếp tục luồng bằng NEXT
  • Forth có cấu trúc trong đó các mảnh rất nhỏ phối hợp với nhau để tạo nên một running system
    • Ở mức thấp, nó đạt được tính linh hoạt và đơn giản, nhưng ở mức cao, mức độ dễ hiểu có thể bị đánh đổi

Code word, colon word và compiler hoạt động trên cùng một interpreter

  • SWAP, DUP, DROP cho thấy primitive của Forth có thể được triển khai trực tiếp bằng machine code đến mức nào
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 dùng call/return stack của i386 làm parameter stack của Forth, nên triển khai stack operation bằng poppush native
  • nasmjf có 130 code word, phần lớn là vì hiệu năng
    • Có một mức tối thiểu về mặt lý thuyết cho số machine-code word cần thiết trong một hệ Forth có thể bootstrap
    • Nếu giảm số primitive quá mức, phần code Forth còn lại có thể trở nên kém hiệu quả và méo mó
    • A 3-INSTRUCTION FORTH FOR EMBEDDED SYSTEMS WORK của Frank Sergeant bàn về một Forth 3-instruction chỉ cần 66 byte trên Motorola MC68HC11
    • sectorforth là Forth x86 16-bit nằm gọn trong boot sector 512 byte
  • Colon word là cách tạo word mới bằng composition các word hiện có
: SDD SWAP DROP DUP ;
  • SDD có hiệu ứng giống như gọi lần lượt SWAP DROP DUP
  • Nhìn từ góc độ indirect threaded code, colon word ở trạng thái đã được compile thành inner interpreter address của ba code word
  • :; trông giống syntax, nhưng thực ra là Forth word
    • : lấy tên word mới và bật compile mode
    • ; hoàn tất dictionary entry mới và tắt compile mode
    • Người dùng có thể thay chính : bằng definition của mình để mở rộng hoặc thay đổi Forth
    • Syntax duy nhất của Forth được xử lý như whitespace giữa các input token
  • Trong Forth, compiling là việc đưa word address hoặc literal cùng push code vào memory
    • Ở normal mode, word được thực thi ngay lập tức
    • Ở compile mode, word address được lưu vào memory
    • Cùng một interpreter đảm nhiệm cả việc thực thi code lẫn compiling code
  • Các control structure như IF...THEN cũng có thể được triển khai bằng chính Forth
: IF IMMEDIATE ' 0BRANCH , HERE @ 0 , ;

: THEN IMMEDIATE DUP HERE @ SWAP - SWAP ! ;
  • Việc ngay cả những yếu tố fundamental như IF cũng được định nghĩa bên trong language là căn cứ cốt lõi cho tiêu đề “Ngôn ngữ lập trình tự viết nên chính mình”
  • Nested comment ( ... ) cũng được triển khai bằng Forth trong jonesforth.f
    • Ngay cả comment cũng được triển khai bên trong language, và người dùng có thể định nghĩa lại nó hoặc thêm cách comment riêng
    • Ví dụ này nhấn mạnh rằng Forth gần như không có native syntax

Dictionary và việc định nghĩa lại tạo nên khả năng mở rộng

  • Dictionary của Forth theo truyền thống dùng linked list, và việc khớp word bắt đầu từ entry mới nhất
    • Definition mới nhất của một word cùng tên sẽ che khuất definition cũ
    • Bất kỳ word nào cũng có thể được định nghĩa lại, kể cả word ban đầu được định nghĩa bằng assembly
    • Word đã được compile trước đó lưu address chứ không lưu tên, nên vẫn trỏ tới address của word trước khi được định nghĩa lại
  • Trong definition mới, có thể gọi word cũ cùng tên để mở rộng word
    • Khi tạo word đệ quy, : ẩn word đang được compile hiện tại khỏi dictionary hoặc đánh dấu nó là inactive
    • Muốn gọi chính nó bên trong word hiện tại thì cần RECURSE
  • Ví dụ biến táo được lấy và biến đổi từ Thinking Forth của Leo Brodie cho thấy tính linh hoạt của Forth
    • VARIABLE APPLES tạo một word APPLES đưa địa chỉ memory lên stack khi được gọi
    • 20 APPLES ! lưu 20 vào địa chỉ đó
    • APPLES ? lấy giá trị và in ra
    • Thinking Forth (PDF) được cung cấp miễn phí
  • Ngay cả khi cần theo dõi riêng táo đỏ và táo xanh, code đang dùng APPLES hiện có có thể không cần thay đổi
VARIABLE COLOR

VARIABLE REDS
: RED REDS COLOR ! ;

VARIABLE GREENS
: GREEN GREENS COLOR ! ;

: APPLES COLOR @ ;
  • APPLES mới cũng là word đưa địa chỉ lên stack, nên cách dùng APPLES !APPLES ? hiện có vẫn được giữ nguyên
  • Địa chỉ chỉ thay đổi thành REDS hoặc GREENS tùy theo màu táo đang active
  • Nhìn từ góc độ ngôn ngữ thông thường, có vẻ một biến đã biến thành hàm, nhưng trong Forth, biến cũng là word đưa địa chỉ lên, hàm cũng là word, nên không có thay đổi khái niệm ở cấp độ ngôn ngữ
  • Ngay cả token trông giống số cũng có thể được định nghĩa lại thành dictionary word
: 4 12 ;
  • Chạy ." The value of 4 is " 4 . CR sẽ in ra The value of 4 is 12

Meow5 và Forth như “con đường ít kháng cự nhất”

  • nasmjf, bản port JonesForth sang NASM, không phải là tái hiện quá trình của Moore mà giống một bài luyện tập “master copy”, quan sát kỹ thành phẩm cuối cùng
  • Sau đó tác giả tiến hành một thử nghiệm concatenative programming cực đoan có tên Meow5
    • Meow5 là thử nghiệm luôn nối và inline toàn bộ code
    • Vì dùng khái niệm parameter stack như Forth nên nó là concatenative
    • Đây là một thought experiment đẩy đến cùng câu hỏi: điều gì xảy ra nếu lưu toàn bộ bản sao hàm thay vì lưu địa chỉ gọi hàm
  • Cốt lõi của Meow5 là inline 100% mọi word
    • Xuất phát từ inline expansion, một tối ưu hóa phổ biến để tránh overhead nhỏ của lời gọi hàm
    • Việc gọi một primitive chỉ có một instruction như DROP thông qua nhiều bước nhảy trông có vẻ lãng phí
  • Meow5 kết thúc như một “thất bại nhỏ đầy thú vị”
    • Bản thân việc inline machine code hoạt động tốt, và file thực thi ELF được xuất ra cũng chạy đúng như dự định
    • Vấn đề là dữ liệu chuỗi: hoặc phải sao chép chuỗi mỗi lần, hoặc phải theo dõi phức tạp word nào dùng chuỗi
    • Word INLINE của Forth, cho phép inline có chọn lọc, được đánh giá là cách tốt hơn
  • Ở cú pháp chuỗi, lời khuyên của Moore một lần nữa được xác nhận
    • Trong Forth, dùng word " nên cần khoảng trắng như " Hello World."
    • Meow5 chọn quoting style tự nhiên dạng "Hello World." và các escape sequence như \n, \"
    • Lựa chọn này buộc tokenizer và interpreter phải xử lý ngoại lệ " ở nhiều nơi, làm giảm tính thuần khiết và đơn giản
  • Khi bắt đầu đi theo con đường Forth, phần còn lại nối tiếp như thể “tự được viết ra”
    • Forth là bootstrapping, là metaprogramming, và có thể trở thành OS lẫn IDE/editor
    • Điều này dẫn đến lập luận rằng khi tạo interpreter đơn giản nhất cho một CPU architecture hoàn toàn mới, rất có thể bạn sẽ viết ra thứ gì đó giống Forth

Các triển khai Forth nhỏ và nơi sử dụng thực tế

  • Forth có thể định nghĩa thêm nhiều Forth ngay trong Forth, và nhiều Forth cũng bao gồm cả assembler
    • Ở phần cuối JonesForth có một stub assembler hoạt động bên trong Forth
    • ;CODE cập nhật header để codeword trỏ tới assembled code thay vì DOCOL
  • PlanckForth là một Forth dạng binary viết tay có kích thước dưới 1KB
    • Một binary ELF hoàn chỉnh cùng một triển khai Forth hoạt động được gói trong dưới 1KB
    • bootstrap.fs khởi đầu từ những toán tử khó hiểu ban đầu, rồi sau vài trăm dòng trở thành Forth dễ đọc
  • Các ví dụ triển khai nhỏ cho thấy khả năng nén cực đoan của Forth
    • SmithForth là Forth bằng machine code do David Smith viết tay, được giới thiệu là một hệ thống Forth 1.000 byte và 1.000 dòng
    • sectorforth là Forth boot sector 512 byte
  • Forth được dùng trong nhà máy điện, robot, hệ thống theo dõi tên lửa, tự động hóa công nghiệp, ngôn ngữ nhúng trong trò chơi điện tử, cơ sở dữ liệu, kế toán, trình xử lý văn bản, đồ họa, hệ thống tính toán, boot loader Open Firmware, cùng nhiều loại bộ xử lý và vi điều khiển
  • Open Firmware là một trường hợp quan trọng xuất phát từ bộ phận kỹ thuật của Sun Microsystems
    • Vì dựa trên interactive programming language, nó cho phép kiểm thử và bring-up phần cứng mới một cách hiệu quả
    • Trong trường hợp Space Shuttle ESN, Open Firmware được xem như công cụ có thể debug phần cứng, phần mềm, driver dạng plug-in và cả bản thân firmware
  • Jupiter Ace là máy tính gia đình của Anh năm 1982, có hệ điều hành là Forth
    • OS và routine library nằm trong ROM 8KB
    • Có trích dẫn năm 1982 rằng Forth tích hợp sẵn “nhanh hơn 10 lần” so với interpreted BASIC và cần chưa tới một nửa bộ nhớ
  • Canon Cat có hệ điều hành là Forth vào năm 1987, chứa OS, bộ ứng dụng văn phòng và môi trường lập trình trong ROM 256KB
    • Đây là sản phẩm hiện thực hóa bằng phần cứng và phần mềm giao diện lấy bàn phím làm trung tâm cùng triết lý thiết kế của Jef Raskin
    • Quy trình vào giao diện Forth trông không giống luồng sử dụng ưu tiên nhất, nhưng nếu biết thao tác thì chỉ cần vài lần nhấn phím

Phần mềm vũ trụ và Forth

  • Một trong những ứng dụng thú vị của Forth là thám hiểm không gian
    • Tàu vũ trụ có chi phí lớn và việc tiếp cận để sửa chữa rất khó hoặc bất khả thi, nên độ tin cậy của phần mềm rất quan trọng
    • Danh sách các dự án NASA dùng Forth khá dài; liên kết gốc đã biến mất nhưng vẫn có bản trên Wayback Machine và bản sao ở forth.com
  • Space Shuttle Small Payload Accommodations Interface Module(SPAIM) là một trường hợp dùng Forth
    • Nhóm phát triển viết routine Forth trên PC, tải xuống rồi kiểm thử tương tác
    • Có trích dẫn rằng trong nhiệm vụ Shuttle STS-45, flight software của SPAIM đã hoạt động không gặp sự cố
    • Forth system của SPAIM hỗ trợ multitasking, mỗi task có stack riêng và một watchdog task giám sát trạng thái stack
  • Space Shuttle Robot Arm Simulator là trường hợp một lập trình viên phát triển một thiết bị phức tạp chỉ trong 5 tuần
    • Nó phải nhận lệnh từ joystick 3 trục để điều khiển một cánh tay dài 50 foot, có 6 khớp và 6 hệ tọa độ
    • Có trích dẫn rằng system này có 14 process riêng biệt
    • Có trích dẫn rằng simulation test kỹ lưỡng đến mức sau khi lắp đặt tại hiện trường, thuật toán executive control không bị thay đổi
  • Shuttle Mission Design and Operations System(SMDOS) là phần mềm điều khiển mặt đất của JPL
    • Trong nhiệm vụ SIR-B, nhiều lỗi phần cứng đã được xử lý tại hiện trường bằng cách sửa phần mềm
    • Sự cố ăng-ten và thay đổi quỹ đạo đòi hỏi một chiến lược thu thập dữ liệu mới, và SMDOS được dùng để hiển thị kế hoạch phù hợp với điều kiện mới
    • Dù mất nhiều dữ liệu, phương thức xoay–chụp–xoay–truyền đã khôi phục được 20% dữ liệu
  • Harris RTX2010 là phần cứng Forth được dùng trong nhiều ứng dụng không gian
    • Thực thi Forth trực tiếp
    • 2 hardware stack sâu 256 word
    • Clock 8MHz và latency thấp
    • Đặc tính radiation-hardened
  • Rosetta và Philae được giới thiệu là nhiệm vụ đầu tiên đưa tàu vũ trụ bay quanh một sao chổi và thả tàu đổ bộ xuống bề mặt sao chổi
    • Ion and Electron Sensor của Rosetta sử dụng Harris RTX2010
    • Philae lander dùng 2 RTX2010 trong CDMS và 2 chiếc để điều khiển ADS
    • Rosetta di chuyển từ năm 2004 đến 2014 và gặp 67P/Churyumov-Gerasimenko
    • 67P rộng 4km và quay quanh Mặt Trời mỗi 6 năm rưỡi
  • Philae bị bounce trong môi trường trọng lực thấp trên bề mặt do harpoon và landing thruster thất bại, nhưng đủ bền bỉ để thực hiện “80%” nhiệm vụ khoa học
  • Cũng có trường hợp patch code cho magnetometer của Galileo năm 1993
    • Magnetometer có RCA1802, RAM 2KB, ROM 2KB và được lập trình Forth bằng hệ thống phát triển dựa trên Apple II
    • Một byte bộ nhớ lỗi xuất hiện ngay giữa code của thiết bị, nên cần patch để không dùng byte đó
    • Người được trích dẫn đã viết từ đầu bằng Lisp một môi trường phát triển Forth cho thiết bị đó cùng trình mô phỏng phần cứng để tạo patch, mất chưa tới 3 tháng làm bán thời gian

Forth giống một ý tưởng và phả hệ hơn là một triển khai đơn lẻ

  • Forth giống một ý tưởng có các khái niệm chung và phả hệ hơn là một triển khai đại diện duy nhất
  • Một trong những lý do khiến Forth khó học là không có một triển khai đơn lẻ nào đại diện độc quyền cho cái tên “Forth”
    • Một số Forth thời kỳ đầu còn có trước cả tên gọi “Forth”
    • Chuẩn Forth tiếp nối từ tài liệu ANS Forth, với Forth 2012 Standard và Forth200x committee được nhắc đến
  • Các Forth chia sẻ khái niệm và các word chung, nhưng Forth chuyên biệt theo mục đích có bộ từ vựng đặc thù riêng
  • Chuck Moore thành lập Forth, Inc vào năm 1973, sau đó đã port Forth sang nhiều hệ thống và tiếp tục tạo ra các hệ thống mới
  • colorForth là môi trường giai đoạn sau của Chuck Moore
    • Màu sắc của mã nguồn thay thế một phần dấu câu trong Forth chuẩn để quyết định cách xử lý word
    • Màu sắc được mô tả là giúp đơn giản hóa ngữ nghĩa của Forth, tăng tốc độ compile và cũng hỗ trợ thị lực không tốt của Moore
    • colorForth bao gồm hệ điều hành 63KB riêng
  • Moore cho rằng khi tính năng liên tục được thêm vào, phần mềm trở nên phức tạp, và không ai dám thay đổi vì sợ những hệ quả ngoài ý muốn
    • Quan điểm này dẫn tới lập luận rằng điều cần thiết là một lập trình viên chuyên trách dành cả sự nghiệp cho một ứng dụng đơn lẻ, liên tục viết lại nó để làm cho nó hoàn hảo

Tính thân thiện với máy, chip Forth, GreenArrays

  • Chuck Moore đã phản đối sự phức tạp của phần mềm từ thập niên 1950; bài viết có trích dẫn cho thấy ông xem các hệ điều hành như Windows, UNIX, DOS là không thể hiểu nổi hoặc không cần thiết
  • Tác giả mô tả triết lý của Moore bằng khái niệm Mechanical Sympathy
    • Cụm từ này xuất phát từ một câu trích dẫn của tay đua Formula One Jackie Stewart, và trong ngữ cảnh phần mềm được Martin Thompson sử dụng trong Why Mechanical Sympathy?
    • Forth có xu hướng được ưa chuộng bởi “những người phần cứng” như kỹ sư điện và nhà thiết kế hệ thống nhúng
  • Niềm say mê thực sự của Chuck Moore dường như nằm ở thiết kế bộ xử lý
    • Harris RTX2000 và RTX2010 được giới thiệu về cơ bản là các chip của Moore
    • Moore bắt đầu thiết kế phần cứng từ gate array Novix N400 năm 1983; thiết kế cải tiến sau đó được bán cho Harris và trở thành các chip RTX
  • Moore thiết kế bộ xử lý bằng phần mềm VLSI tự phát triển OKAD, viết bằng 500 dòng Forth
    • VLSI Design Tools (OKAD) mô tả rằng 500 dòng colorForth cung cấp mọi thứ cần thiết cho thiết kế chip
    • OKAD là một bộ công cụ bao gồm công nghệ cổng logic, bố trí mạch, simulation hành vi điện và export GDSII
  • Novix NC4000 là một engine xử lý siêu nhanh được thiết kế để thực thi trực tiếp các lệnh Forth cấp cao
    • Nó đạt được hiệu năng bằng cách loại bỏ assembly language thông thường và microcode nội bộ
    • Kiến trúc dual stack làm giảm đáng kể overhead khi triển khai subroutine
  • Chip GreenArrays được giới thiệu xoay quanh bài thuyết trình năm 2013 của Moore, “Programming a 144-computer chip to minimize power”
    • Có 144 máy tính bất đồng bộ trên một chip
    • Core nhàn rỗi dùng 100 nW, core hoạt động dùng 4 mW, chạy ở 666 Mips rồi trở lại trạng thái nhàn rỗi
    • Khi tất cả máy tính hoạt động ở tốc độ tối đa, mức tiêu thụ điện là 550 mW, khoảng 0,5 W
  • Tài liệu GreenArrays Architecture nhấn mạnh “NO CLOCKS”
    • Việc tạo và phân phối clock trong máy tính thông thường tiêu tốn nhiều năng lượng ngay cả khi chờ, nhưng không làm được việc gì
    • GreenArrays được giới thiệu không phải là Multi-Core CPU mà là Multi-Computer System

Sự đơn giản, hiệu quả và tương lai của điện toán công suất thấp

  • Tác giả cho rằng phần mềm và phần cứng đã tiếp tục đi theo hướng chồng thêm ngày càng nhiều lớp phức tạp
    • Điện toán trong các trung tâm dữ liệu lớn được nhìn nhận là rẻ hoặc miễn phí vì được trả gián tiếp bằng chi phí quảng cáo
    • Thứ thực sự được dùng để trả là sự chú ý và dữ liệu cá nhân của người dùng
  • Tác giả lập luận rằng trong tương lai, không có lý do gì để tiếp tục dùng phần mềm ngày càng kém hiệu quả, được làm cẩu thả hơn, cùng các yêu cầu phần cứng ngày càng dốc hơn
  • Các ngôn ngữ giống Forth có thể có tương lai mạnh mẽ trong những lĩnh vực sau
    • Máy tính nhỏ và hiện diện ở khắp nơi
    • Nguồn điện mặt trời
    • VM bị ràng buộc chặt chẽ
  • Dennard scaling gần như đã dừng lại vào khoảng năm 2006
    • Mối quan hệ trong đó transistor nhỏ hơn cho phép tốc độ cao hơn và điện áp thấp hơn đã chạm ngưỡng đình trệ quanh mức 4GHz do rò rỉ dòng điện và nhiệt
    • The Free Lunch Is Over của Herb Sutter là bài viết bàn về việc cách tăng hiệu năng CPU đang chuyển sang hyper-threading và multicore
  • Sutter cho rằng cần thiết kế lại ứng dụng cho phù hợp với tính đồng thời, hoặc viết mã hiệu quả hơn và ít lãng phí hơn
    • Ông nói tối ưu hóa hiệu năng sẽ không kém quan trọng đi, mà sẽ trở nên quan trọng hơn
  • Ngày nay, ta có thể mua một microcontroller mạnh hơn IBM 704 rất nhiều chỉ với vài đồng xu, và có thể viết một Forth system mạnh mẽ trên đó
    • Microcontroller có thể chạy bằng pin coin cell hoặc một tấm pin mặt trời nhỏ
    • Tác giả tiếp đó nói rằng chưa từng có thời điểm nào tuyệt vời hơn cho điện toán quy mô nhỏ
  • Để hiểu Forth, cần cân nhắc sự khác biệt giữa “simple” và “easy”
    • Simple Made Easy của Rich Hickey được giới thiệu là bài thuyết trình giúp nói về sự phân biệt này
    • Forth không dễ và có thể không phải lúc nào cũng thú vị, nhưng chắc chắn là một ngôn ngữ đơn giản
  • Growing a Language của Guy Steele là bài thuyết trình cho thấy ngôn ngữ được xây dựng từ các primitive như thế nào
    • Có thể áp dụng cho Forth câu trích dẫn về Lisp rằng khi từ mới do người dùng định nghĩa trông giống primitive, và primitive cũng trông giống từ do người dùng định nghĩa, thì nó trở thành một ngôn ngữ lớn hơn, liền mạch
  • Lời khuyên cuối cùng là hãy tạo ra ngôn ngữ lập trình hoàn hảo cho chính mình

1 bình luận

 
GN⁺ 2023-07-18
Bình luận trên Hacker News
  • Ngay khi biết đến Forth, tôi đã nghĩ mình phải tự làm thử một cái, và 2 năm trước đã tạo ra MiniForth chỉ trong một tuần
    Ban đầu nó nhắm tới Blue Pill và Arduino nguyên bản, nhưng tôi phát triển nó như một trình biên dịch chéo để có thể kiểm thử trên máy host
    Tôi bị cuốn đến mức ngày nào tan làm cũng mong đến lúc được ngồi nghịch tiếp, và cuối cùng hoàn thành chỉ trong 5 buổi tối ngày thường cùng một ngày cuối tuần
    Tôi rất khuyến khích quá trình này; trải nghiệm duy nhất đem lại cảm giác khai sáng tương tự với tôi là lần đầu tiếp xúc với macro Lisp(https://www.thanassis.space/score4.html#lisp)
    • Đúng vậy. Trong môn kiến trúc máy tính năm nhất, chúng tôi phải làm một dự án cuối kỳ tự chọn cho LC-3, và vì trước đó tôi từng nghịch Forth một chút qua mod Minecraft RedPower 2 nên đã nghĩ triển khai nó chắc sẽ rất vui
      Nó ngốn gần như toàn bộ thời gian rảnh của tôi trong học kỳ đó, và có một ngày tôi chỉ nhìn đồng hồ sau khi thấy trời bắt đầu sáng mới nhận ra mình đã thức trắng đêm
      Tôi chưa từng dùng Forth một cách thực dụng trong đời thực, nhưng trải nghiệm tự xây một cái từ đầu thật sự gần đến mức có thể gọi là một trải nghiệm tôn giáo
      Nó giống như phiên bản chưng cất tinh khiết của điều Fred Brooks nói về lập trình: lập trình viên, như thi sĩ, làm việc chỉ cách rất ít so với chất liệu thuần túy của tư duy; xây lâu đài trên không chỉ bằng trí tưởng tượng; và chương trình là ma thuật có thật, nơi nếu bạn đọc đúng câu thần chú thì thứ chưa từng tồn tại trước đó sẽ sống dậy trên màn hình
    • Hoàn toàn đồng ý. Rất lâu trước đây tôi từng viết một trình biên dịch Forth bằng ZX81 BASIC
      Việc in ra 1000 con số trên màn hình từ chỗ mất 19 giây đã thành gần như tức thì
      Và tôi cũng học được một bài học lớn: khi nhìn vào mã máy được tạo ra, tôi tưởng nó đã hoàn hảo và không thể cải thiện thêm, nhưng hôm sau quay lại thì lại làm được một phiên bản nhanh hơn nhiều
  • Bạn có thể thắc mắc: “Viết chính nó là thế nào? Chẳng phải chỉ là có thể viết hàm thôi sao?”
    Ở mức nào đó thì đúng, nhưng Forth đi xa hơn ở chỗ bạn có thể định nghĩa các từ mới để chúng trở thành một phần của chính ngôn ngữ
    Các từ này có thể được dùng như các phép toán tích hợp sẵn, và thậm chí có thể thay đổi cách ngôn ngữ hoạt động
    Vì là một ngôn ngữ có thể mở rộng, bạn còn có thể tạo ra các từ để định nghĩa cấu trúc điều khiển mới hoặc thay đổi cú pháp, và mức linh hoạt này không hề phổ biến ở các ngôn ngữ khác
    Ở khía cạnh đó, Forth có thể được xem là ngôn ngữ “tự viết chính nó”, vì lập trình viên có thể tùy biến và mở rộng ngôn ngữ ở một mức rất nền tảng
    Nó cũng tương tự hệ thống macro của Lisp: cũng như macro Lisp cho phép tạo ra các cấu trúc cú pháp mới và ngôn ngữ đặc thù miền thông qua biến đổi ở thời điểm biên dịch, các từ của Forth cũng cho phép mở rộng cú pháp và chức năng
    • Nghe thì hay đấy, nhưng trong gần 40 năm làm lập trình viên chuyên nghiệp, vấn đề của tôi chưa bao giờ là cú pháp mà luôn là ngữ nghĩa
      Có thể sẽ có những trường hợp như nhân ma trận, nơi viết A = B + C * D; tốt hơn là phải liệt kê từng hàm cần gọi, nhưng thực tế tôi chưa từng gặp vấn đề kiểu đó
      Tôi không rõ là do mình thiếu trí tưởng tượng, hay nó chỉ hữu ích trong những lĩnh vực nhất định mà tôi chưa từng làm, hay cú pháp Forth quá nghèo nàn nên phải mở rộng mới dùng được, hay đơn giản là mọi người muốn tùy biến ngôn ngữ như độ xe
      Tôi thật sự không hiểu vì sao người ta lại hứng thú với chuyện này đến vậy
  • Một trong những dự án Forth thú vị nhất hiện nay là Dusk OS, một hệ điều hành 32-bit được viết bằng Forth, có kèm cả trình biên dịch C riêng và đang được port sang nhiều nền tảng
    https://duskos.org/
    • Tôi không rõ riêng DuskOS thế nào, nhưng xét về lịch sử thì dù Forth đúng là từng là “hệ điều hành của chính nó”, nó vẫn khá thô sơ nếu đem so với thứ mà độc giả hiện đại hình dung khi nghe đến hệ điều hành
      Đúng là bạn không thể kỳ vọng nhiều vào thứ chạy được trong 8KB RAM, nhưng dù nó cung cấp các chức năng nguyên thủy, về mặt lịch sử nó gần như không có driver hay phần lớn các khái niệm trừu tượng hóa
      Mã được nạp từ source nên chậm, việc liên kết gần giống như nạp các block theo đúng thứ tự, và để nạp chương trình mới thì trước hết phải gỡ chương trình hiện tại ra
      Tôi cũng không chắc nó tốt hơn CP/M là bao, vốn thường khởi động lạnh lại máy khi chương trình kết thúc, nhưng ít nhất CP/M còn tách riêng BIOS và BDOS
    • Cái này tôi đã bỏ lỡ. Tôi vừa mới đọc “Beyond the Collapse”, và cảm giác là với trình độ Lisp hay APL/J, C của mình, tôi khó mà chạm tới được sự đơn giản của Forth ở cấp độ hệ điều hành
      Tôi nhất định sẽ xem thử trước cuối tuần tới
  • Ngôn ngữ lập trình đầu tiên của tôi là x86 assembly và Forth. Bố tôi mê Forth, và tôi học lập trình từ ông
    Khi còn tuổi teen, tôi đã viết vài hệ thống x86 Forth cho DOS, và cái cuối cùng thậm chí còn là một bản triển khai tương thích ANS khá hoàn chỉnh tên là “Third”: https://github.com/benhoyt/third
    Việc có được một trình biên dịch Forth tự bootstrap hoàn chỉnh, kèm cả assembler, chỉ trong vài nghìn dòng mã là điều khá đáng kinh ngạc
    Gần đây tôi còn chép lại một bài viết cũ mà mình từng đồng tác giả cho tạp chí Forth Dimensions
    Ý tưởng của Forth đến giờ vẫn rất hay, nhưng thao tác trên stack rất nhanh trở nên nhàm chán và cũng cực kỳ khó đọc
    Bạn có thể thấy điều đó trong ví dụ mã ở https://benhoyt.com/writings/forth-lookup-tables/, đặc biệt là Search-Table. Đặt tên đã khó, nhưng có vẻ không đặt tên còn khó hơn
    • Việc thao tác stack trở nên nhàm chán có lẽ là vì bạn và tôi đều không phải Chuck Moore
      Mã của ông ấy nhìn chung có rất ít việc đảo trộn stack. Ví dụ: http://www.merlintec.com/download/color.html
    • Tôi vừa lướt qua mã nguồn của Third, khá thú vị
      Tôi thấy khi bootstrap nó gọi kernel.com, nên hơi tò mò không biết kernel.com được build như thế nào
  • Bài nói chuyện liên quan của Chuck Moore: “Programming a 144 Computer Chip to Minimize Power” (2013)

https://www.youtube.com/watch?v=0PclgBd6_Zs
Có vẻ Forth vận hành các máy tính siêu tiết kiệm điện theo cách này: GreenArrays đang xuất xưởng chip bất đồng bộ 144 lõi, và chỉ cần 7 pJ/inst năng lượng
Các lõi nhàn rỗi không tiêu thụ điện (100 nW), còn các lõi hoạt động chạy rất nhanh ở mức 4 mW (666 Mips) rồi chuyển sang trạng thái nhàn rỗi trong khi chờ giao tiếp

  • “Tôi luôn nghĩ kích thước và tốc độ chỉ quan trọng với dân nghiệp dư. Nhưng trong bối cảnh hiện đại, chỉ có đúng ba tham số quan trọng: điện năng, điện năng, điện năng
    --Chuck Moore
    https://youtu.be/0PclgBd6_Zs?t=389
  • Tôi thực sự tự hỏi liệu kiểu cấu trúc topo này có quay trở lại trong vài năm tới không
  • Tài liệu nhập môn tuyệt vời là Starting Forth
    Trong đó có minh họa hấp dẫn nhất mà tôi từng thấy trong sách giáo khoa
    [0] https://www.forth.com/starting-forth/
  • Hồi xưa khi OS/2 ra mắt, một người bạn nói với tôi rằng “chương trình OS/2 không thể viết bằng assembler, phải viết bằng C”
    Tôi phản ứng lại bằng cách tạo ra Forth/2
    Đó là một trình biên dịch Forth native code dạng direct-threaded cho OS/2, được viết bằng assembler; Brian Matthewson đã viết một bộ tài liệu hướng dẫn rất hay cho nó, và nó đã có vài chục người dùng
    [1] https://sourceforge.net/projects/forth2/
  • Hơi lạc đề một chút, nhưng tôi nhớ là mình đã đọc bản nguyên mẫu ban đầu của bài này dưới dạng thuyết trình
    Về cơ bản nó giống bài hiện tại, nhưng ít chữ hơn nhiều và có nhiều khoảng trống hơn
    Tôi nhắc đến nó vì tài liệu đó cũng cho thấy vẻ đẹp của chủ nghĩa tối giản ở mặt công nghệ website mà nó dùng làm nền
    [0] http://ratfactor.com/forth/forth_talk_2023.html
    [1] http://ratfactor.com/minslides/
    • Có điều gì đó chung giữa việc tự làm Forth của riêng mình và tự làm phần mềm trình chiếu đơn giản của riêng mình chăng? https://www.mankier.com/1/techtalk-pse
  • Thật thú vị khi Rust cũng có trình biên dịch Forth. Tài liệu liên quan ở [1]
    Cách sử dụng vẫn còn hơi chưa rõ[2], nhưng trước đây cũng từng được bàn đến ở đây[3], và phần triển khai có vẻ chắc chắn
    Không phải là máy ảo Forth kiểu REPL, nhưng là một triển khai máy ảo rất ấn tượng
    Nếu FORTH là một máy ảo, tôi từng nghĩ nó có thể là lựa chọn tối ưu khi cần một hệ thống nhỏ và hiệu quả để xử lý dữ liệu streaming với hiệu năng gần bare metal
    Ngoài ra còn có điểm là không phải vật lộn với hệ điều hành
    Điều này về bản chất chẳng phải là làm trên CPU tiêu chuẩn những gì FPGA vẫn làm sao?
    Tuy vậy, tôi đang hình dung một hệ thống chuyên dụng nơi không cần tự viết mọi driver chỉ để kết nối với phần cứng cần thiết
    [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
  • Tôi cũng đã tự triển khai thêm một Forth nữa
    Mục tiêu không phải là sao chép trung thành ý tưởng gốc, nên nó hoạt động hơi khác
    Vì bài viết nói rằng có thể khám phá Forth, tôi cũng để lại bản triển khai của mình: https://github.com/loscoala/goforth
    Khác biệt lớn nhất là trong biến thể Forth này, văn bản nguồn được chuyển hoàn toàn thành bytecode, và không có runtime theo nghĩa Forth cổ điển
    Vì vậy rất dễ dịch bytecode sang C
    Tôi dùng Forth này để sinh mã C, rồi nhúng đoạn mã đó vào phần mềm khác để sử dụng
    • Cách làm đó có thể rất hiệu quả và thông minh, nhưng vẫn cần luôn ý thức rằng kiểu giải pháp đa ngôn ngữ này về lâu dài rất dễ trở thành cơn ác mộng bảo trì
      Có một dự án mã nguồn mở rất hay giúp luyện nghe và đọc nhạc trực tiếp, được viết bằng ngôn ngữ do chính tác giả tạo ra, và ngôn ngữ đó lại biên dịch sang JavaScript
      Việc thiết lập chuỗi công cụ phiền phức đến mức dù biết khá nhiều lỗi tồn tại, tôi vẫn chưa dám sửa
      https://sightreading.training/
      https://github.com/leafo/sightreading.training
      Dự án này được viết bằng ngôn ngữ tên là ‘Moonscript’: https://github.com/leafo/moonscript
      Moonscript biên dịch sang Lua, còn Lua lại biên dịch sang JS
      Đúng là điên rồ. Một kiểu điên rồ rất ngầu, nhưng dù sao nó cũng khiến tôi không trở thành người đóng góp cho dự án