Artikel ini adalah akhir dari serangkaian artikel eForth pada kalkulator yang dapat diprogram. Mulai dari siniPerintah bahasa input "Elektronik MK-161" hanya menempati setengah file eForth0.mkl. Paruh kedua ditempati oleh tabel, yang perkembangannya tidak kalah sulit daripada menulis bagian algoritmik penerjemah. Mari kita coba mencari tahu bagaimana tabel ini digunakan.

Profesor Wirth mengajarkan bahwa "pemrograman dalam kecil" terdiri dari pengembangan dua komponen yang sama pentingnya - algoritma dan struktur data.
Kami telah menemukan satu struktur data eForth. Ini adalah badan VCA (kata-kata tingkat tinggi) yang terletak di memori byte. Empat penangan menafsirkan bidang parameter VCA "mereka sendiri" dengan cara yang berbeda:
.DB DOVAR ; .DB β¦ ; .DB DOCON ; .DW _ ; .DB DOCONM ; .DW _ ; .DB DOLST ; .DW 1, 2,β¦ EXITT ;
Struktur data yang relatif sederhana berikut dikaitkan dengan TYPE "pesan standar."
Semua pesan eForth diberi nomor dan ditransfer ke memori program yang murah. Jika kata TYPE mencetak satu huruf, kodenya mungkin nomor pesan tersebut, dari 0 hingga 7.
; TYPE .BASE tblTYPE: .DBB str7,str6, str5, str4, str3, str2, str1, str0
Dalam bahasa MK yang diperluas, perintah .BASE pseudo menetapkan "basis" untuk perintah .DBB, yang secara berurutan menempatkan garis offset str7, str6, dalam byte, dll. relatif terhadap label dasar tblTYPE. Menambahkan angka dari 0 hingga 7 ke alamat tabel, offset ini dapat dibaca darinya. Menambahkan offset yang ditemukan ke tblTYPE, kami mendapatkan alamat dari baris yang diinginkan.
Byte pertama dari string berisi panjangnya. eForth banyak menggunakan
garis penghitungan tersebut .
Kami juga menemukan tabel tblTokens, yang mencantumkan alamat kode dari semua 208 kata yang tertanam. Jika kata itu tidak primitif, tabel berisi 0. Pergi ke alamat 0 akan menyebabkan eForth untuk reboot, dengan mencicit.
Tabel tblNames juga disebutkan, merujuk pada nama-nama dengan 208 kata yang sama. Nama-nama ini dalam bentuk garis penghitungan disimpan dalam memori program "karet" yang sama. Tabel tblNames itu sendiri tidak akan tersedia saat eForth berjalan, tetapi informasi yang terkandung di dalamnya tidak akan hilang. Pada waktu kompilasi, eForth.f akan mentransfer alamat nama ke struktur data yang lebih nyaman disimpan dalam memori desimal (lihat 2).
Saya juga berbicara tentang tblCHPUT, tabel kode kontrol asosiatif ketika menampilkan surat di layar kalkulator. Tujuh tabel lainnya, dari tblKeyNum ke tblKeyRusF, menerjemahkan kode tombol yang ditekan dalam mode keyboard yang berbeda menjadi kode huruf 8-bit. Alamat subrutin yang bertanggung jawab untuk mode papan ketik aktif ada di register desimal ptrKbdInt.
Secara total, hanya satu struktur data yang belum dirangkai dalam file eForth0.mkl, ini adalah tabel pengenalan nama. Kami meninggalkan mereka untuk pencuci mulut (lihat 5) setelah hidangan utama - dua tabel pos disimpan dalam memori desimal. Pertama, kita akan mempersenjatai diri kita dengan alat untuk "mengisi" pos-pos ini.
1. Bekerja dengan pos: KEPALA! dan KEPALA @
HEAD! ( xt nfa r -- ) r, xt nfa. HEAD@ ( r -- xt nfa lex ) r, xt, nfa .
Satu register desimal MK-161 dapat menghafal 12 tempat desimal. eForth menggunakan register ini untuk menyimpan tiga angka kecil, masing-masing dari 0 hingga 9999.
Tiga "bidang" untuk menyimpan angka-angka ini saya sebut A, B dan C: AAAABBBBCCCC. Tanda desimal hanya merujuk ke bidang A.
HEAD @ primitive mendapatkan nomor register dan membagi nomor dari sana ke dalam bidang, dan HEAD! mengumpulkan bidang dalam jumlah panjang dan menulis "monster" yang dihasilkan di register yang ditentukan. Namun ada nuansa.
"Judul desimal" dari kata tersebut berisi di bidang A alamat namanya (nfa). Jika alamat ini negatif, nama disimpan di memori program. Kolom B berisi kata token (xt). Field C disebut leksikon. Ini menyimpan bit SEGERA dan tanda bahwa kata itu dimaksudkan hanya untuk kompilasi.
HEAD @ membagi header menjadi beberapa bagian. Di bagian atas tumpukan adalah bidang leksikon C, di bawahnya adalah bidang nama A. Bidang B, di mana token biasanya disimpan, berada di bagian paling bawah.
KEPALA! mengatur ulang bidang C.
2. Judul sebaris

Header dari masing-masing 208 kata bawaan (0 hingga 207) berjalan berurutan, dimulai dengan R44. Field A selalu berisi angka negatif, karena nama-nama kata ini di-hardcode dalam memori program.
Kolom B dan C dapat diedit. Oleh karena itu, pengguna dapat mendefinisikan kembali kata-kata bawaan dan membuat SEGERA mereka butuhkan dari mereka (lihat 4).
3. Judul pengguna

Bekerja dengan hanya 208 nama yang telah ditentukan menghemat memori byte, tetapi sangat membosankan. Oleh karena itu, saya mengembangkan struktur data lain di mana fantasi dalam memilih nama hanya terbatas pada 32 huruf. Struktur ini terdiri dari 32
daftar , yang masing-masing bertanggung jawab atas kata-kata pengguna dengan panjang tertentu. Masing-masing dari 32 daftar ini memiliki tajuk pribadi. Daftar itu sendiri melompati memori desimal, tetapi header mereka selalu disimpan dalam R301 ... R332.
Menyortir kata berdasarkan panjang nama adalah sorotan penting 161eForth. Penyortiran sangat mengurangi jumlah perbandingan saat Anda mencari kata dengan namanya, mempercepat kompilasi. Siapa yang butuh fungsi hash jika setiap nama memiliki panjang yang diketahui?
Untuk kesederhanaan,
judul daftar memiliki struktur yang sama dengan bidang A, B, dan C sebagai judul kata. Tujuan bidang ini berbeda. Bidang A berisi nomor register pertama dalam daftar. Bidang B berisi jumlah register yang disediakan untuk daftar. Field C menyimpan jumlah kata yang posnya sudah ada dalam daftar.
Pada awal pekerjaan, bidang C sama dengan nol, kata-kata tidak ada di semua daftar. Kolom B adalah 2, setiap daftar diberikan beberapa register untuk memulai. Bidang A menunjukkan blok 2 register yang dimulai dengan R333.
Setiap daftar berisi judul kata. Kami telah membongkar mereka (lihat. 1). Di sini, mungkin, alamat nama (nfa) akan positif dan menunjuk ke garis penghitungan, yang secara tradisional disimpan di depan badan VCA. Juga, token di bidang B adalah alamat bidang kode (cfa) yang masuk ke memori biner segera setelah nama ini. Ada satu pengecualian -
jika kata sudah ditentukan, bidang A akan menunjuk ke nama lama. Mengapa menyimpan string lagi? Memori biner itu mahal.
Ketika semua register daftar penuh (B = C), kata PUBLISH menyediakan 5 tempat lebih bebas, mendorong struktur data ini di tempat yang tepat dan menyesuaikan tautan (A) dalam header daftar.
4. Publikasi kata baru: BEKERJA dan MENERBITKAN
LAST ( -- a ) . WORK ( -- a ) . PUBLISH ( -- ) . $,n ( nfa -- ) , nfa. ?UNIQUE ( a -- a ) , .
Struktur data yang dikembangkan untuk MK-161 untuk menyimpan judul kata ternyata praktis dan mudah diintegrasikan ke dalam eForth. Ketika BUAT, KONSTAN atau: membuat kata baru, mereka mengakses kata sistem $, n untuk membuat judul kata dengan nama yang diberikan. $, n merujuk pada? UNIK untuk verifikasi - apakah kita membuat kata baru atau mendefinisikan kembali yang lama?
Jika sebuah kata dengan nama yang sama sudah ada ,? UNIQUE memperingatkan pengguna tentang hal ini. Pada saat yang sama, alamat header yang didefinisikan ulang dimasukkan dalam variabel sistem LAST. Untuk kata baru, LAST diatur ulang ke nol.
Dalam kasus apa pun, $, n membuat header baru dalam variabel WORK - itu adalah register desimal yang dapat menyimpan 12 bit header. Jika nama itu tidak ditemukan, itu dimasukkan dalam kamus sebelum bidang kode, seperti yang terjadi di 86eForth dan banyak Benteng lainnya.
MK-161 berhasil dilakukan tanpa "bidang komunikasi" , ini juga menghemat memori biner.
Primitif PUBLISH melengkapi definisi kata. Ketika mengkompilasi kata-kata titik dua, PUBLISH dipanggil dari;; akibatnya, bit SMUDGE tidak diperlukan. Tempat di mana header dari WORK disalin ditentukan oleh variabel LAST. Jika LAST nol, header baru dibuat dalam daftar yang sesuai (lihat 3). Apakah daftar sudah lengkap? Kemudian PUBLISH akan menambah 5 register lagi, empat di antaranya untuk masa depan.
Setelah menjalankan PUBLISH, variabel LAST selalu menunjuk ke judul kata terakhir. Ini membantu SEGERA melakukan tugasnya dengan mengubah bidang leksikon.
5. (CARI) dan tabel pengenalan nama
(FIND) ( a -- r T | a F ) r, a. FIND ( a -- a F | xt 1 | xt -1) . 1, IMMEDIATE.
A primitive (FIND) mengelola pencarian kata dengan namanya. Pertama, ia mencari nama di antara kata-kata bawaan dengan nama-nama yang diketahui sebelumnya, kemudian memeriksa daftar kata-kata pengguna dengan panjang nama yang diinginkan (lihat 3). Tabel pengenalan nama sangat mempercepat ini "pertama". Begini cara kerjanya.
Pada awalnya (FIND) menemukan alamat tabel asosiatif utama dalam array tblLen, di mana nama-nama yang diketahui dari panjang yang dibutuhkan "disiapkan". Dalam tabel ini (CARI) mencari karakter pertama dari nama. Dalam kebanyakan kasus, ini segera memungkinkan Anda untuk mengetahui
nomor register judul kata yang dicari - dengan huruf pertama dan panjangnya.
Kebetulan beberapa kata dengan panjang yang sama memiliki huruf pertama yang sama. Kemudian alih-alih nomor register (FIND), itu tersandung pada alamat tabel asosiatif berikutnya (angka baca adalah 300 atau lebih) dan pencarian berlanjut pada huruf kedua. Dan seterusnya, sampai kata itu ditemukan atau ditetapkan bahwa tidak ada kata seperti itu.
Tentu saja, setelah kecocokan untuk huruf pertama (FIND), seluruh nama diverifikasi. Tetapi
tabel pengakuan membuat eForth cepat . Musim semi ini, saya menginvestasikan banyak waktu saya di dalamnya, dan sekarang mereka menghemat waktu pencarian. "Kunci" di dalamnya bahkan disortir berdasarkan abjad. Maaf, firmware MK-161 meludahinya.
Demi kompatibilitas, saya menerapkan kata FIND dari Fort ANS [4], yang mempercayai primitif "pekerjaan hitam" (FIND). Kata sudah dipertimbangkan? UNIK juga mencari argumennya melalui (FIND).
6. Penerjemah eksternal
Buku [1] berisi deskripsi lengkap eForth, termasuk penerjemah βteksβ eksternal. Dialah yang mengeksekusi atau mengkompilasi teks sumber dalam bahasa Fort. Perbedaan dari penafsir teks dari dialek Fort lainnya ([2], [3]) telah muncul selama beberapa dekade terakhir, tetapi ada beberapa dari mereka.
Di bawah ini adalah diagram blok penerjemah teks yang diambil dari [1]. Hati-hati - "penerjemah" ini memiliki mode kompilasi! Kata $ COMPILE bertanggung jawab untuk mengkompilasi teks Forte ke dalam "kode dijahit", eksekusi yang kami teliti dengan sangat detail pada artikel pertama. Ketika $ INTERPRET dijalankan sebagai gantinya, kata-kata yang dimasukkan dieksekusi segera - mode interpretasi. EVAL "menghitung" seluruh string yang dimasukkan, memanggil salah satu dari dua kata ini untuk setiap kata yang dimasukkan.

Setelah diagram blok, penulis mendekripsi blok mana yang tidak. Ini terjemahannya. Nama blokir biasanya cocok dengan nama kata eForth. Kata NAME? tidak ada dalam implementasi saya, ini berhasil diganti dengan cepat (FIND) (lihat. 5).
Buku ini juga menyediakan kode sumber untuk setiap kata eForth dalam versi Windows, dengan penjelasan singkat. Apa versi untuk MK-161 berbeda, saya sudah bilang. Kode sumber untuk implementasi saya ada di arsip:
the-hacker.ru/2019/161eforth0.5b.zipAkhirnya, saya akan menyebutkan implementasi kata
(PARSE) dalam bahasa MK-161 - di bawah Windows itu adalah VCA. Debugging membutuhkan waktu satu minggu, tetapi
mempercepat kompilasi hingga setengahnya . Kata (PARSE) melakukan semua "pekerjaan kotor" untuk PARSE untuk mengisolasi kata-kata individual dari aliran teks input.
Tambahan saya pada interpreter eksternal adalah dua kata, sebagai tambahan dari loop QUIT yang biasa: TLOAD yang telah disebutkan dan diambil dari versi FILE yang lebih lama. Kata FILE menerjemahkan I / O ke konsol, tetapi membaca baris untuk interpretasi dari port RS-232. Setelah berhasil memproses setiap baris, surat dengan kode 11 adalah output ke port. File yang diunduh dari komputer harus diakhiri dengan kata QUIT.
Saya belum men-debug kata FILE. Jika ada yang membutuhkannya, bagikan kesan Anda.
Ulasan 161eForth dari titik-titik ketat telah berakhir, tetapi Fort adalah alat yang sangat fleksibel yang dapat disesuaikan setiap pemilik. Bahkan ketika Anda telah benar-benar memikirkan segalanya, seseorang di suatu tempat di planet ini akan menemukan trik lain yang dapat mengejutkan Anda.
Berikut adalah kata-kata terakhir dari penulis eForth dari [1]:
Selama 26 tahun, saya telah menulis ulang eForth berulang kali. Dalam setiap sulih suara, saya mencoba membuatnya lebih sederhana dan lebih jelas. Sekarang di 86eForth v5.2, saya pikir saya telah mencapai kebenaran dan karenanya sangat bahagia.
Seperti yang dikatakan Einstein:
Semuanya harus dilakukan sesederhana mungkin, tetapi tidak sederhana.
Membuat 86eForth v5.2 menjadi lebih mudah, mungkin merusaknya atau tidak berguna sebagai alat pemrograman.
Sastra
- Dr. Chen-Hanson Ting. eForth dan Zen - Edisi ke-3, 2017. Tersedia di Amazon Kindle.
- Baranov S.N., Nozdrunov N.R. Bahasa Fort dan implementasinya. - L.: Teknik mesin. Leningrad Departemen, 1988.
- Semenov Yu.A. Pemrograman dalam bahasa FORT. - M.: Radio dan komunikasi, 1991.
- ANS Keempat standar. X3.215-1994. Terjemahan
- Dokumentasi SP-Forth .
- Offete Enterprises (Dr. Chen-Hanson Ting) , penulis 86eForth v5.2, dalam bahasa Inggris.
- Kisah Mikhail Pukhov "True Truth" dengan program "Moonwalker-1", di mana saya mendapat KDPV dan cinta untuk kalkulator Soviet.