Fitur implementasi bahasa MSH

Saya melanjutkan serangkaian artikel tentang bahasa pemrograman MSH. Dalam artikel sebelumnya, saya sudah menggambarkan spesifikasi bahasa ini. Namun spesifikasinya tidak mengungkapkan semua fitur bahasa. Saya ingin menghilangkan celah itu dengan artikel ini. Tentu saja, saya tidak berhasil menggambarkan semuanya, tetapi pada dasarnya saya menggambarkan fitur utama. Kami akan menunda sisanya sampai waktu yang lebih baik.

Ketika gambar bahasa terbentuk, tampaknya semuanya logis dan konsisten. Tetapi di pintu masuk ke implementasi bahasa ada masalah yang harus diselesaikan dengan memilih satu atau strategi lainnya. Sekarang setelah penerjemah bahasa siap, Anda dapat melihat bagaimana itu memecahkan satu atau lebih masalah implementasi.

Konsep bahasa pemrograman MSH


Daftar Isi


pengantar 2
Organisasi program. 2
runtime. 2
Manajemen data. 3
Pelokalan data. 3
Sintaks singkatan. 5
Konstanta. 5
Fitur dari beberapa tim. 5
perintah KONSTAN. 5
perintah XECUTE. 6
Perintah COPY dan MOVE. 6
Sinkronisasi sumber daya. 7
Bentuk disingkat dari perintah SET. 8
Tim blok. 8
JIKA perintah. 8
perintah KASUS. 9
perintah SAAT. 10
Blokir iterator loop. 10
Tim BERIKUTNYA. 11
perintah KEMBALI. 12
tim QUERY. 12
Perintah non-blok Perintah traversal data tree. 12
Tim NEXT1. 12
Perintah BACK1. tigabelas
QUERY Team1. 13
Manajemen pelaksanaan program. 13
Melewati parameter. 14
Penanganan acara. 15
perintah EVENTTRAP. 15
Tim EVENTDELETE. 16
Tim EVENTCALL. 16
Tim EVENTWAIT. 16
vektor. 16
vektor 64 bit. 16
vektor 32 bit. 17
16 bit vektor. 17
8 vektor bit. 17
Operasi. 17
benda. 18
Warisan benda. 19
Pertukaran dengan file. 20
Kesimpulan. dua puluh

pengantar


Bahasa MSH dibangun di atas konsep-konsep bahasa MUMPS. MUMPS adalah bahasa yang kurang dikenal yang dikembangkan pada abad terakhir. Tetapi masih digunakan dalam aplikasi informasi. Informasi tentang bahasa ini ada di Internet. Ada implementasi yang berhasil dari bahasa ini dan komunitas programmer yang mendukungnya. MUMPS sedang dikembangkan di AS dan Rusia. Selain itu, itu digunakan, sejauh yang saya tahu, di Amerika Latin, Jerman, Australia, dan Cina. Secara umum, konsep bahasa ini hidup. Saat bertemu dengan MUMPS, sifatnya yang kuno mencolok. Pengembangan ini dirancang untuk menghilangkan kekurangannya, sambil mempertahankan keunggulan, kesederhanaan, konsistensi, organisasi data.
Organisasi program.

Unit terjemahan adalah modul bahasa MSH. Modul dimulai dari 8 byte standar yang mengidentifikasi versi bahasa. Di awal baris mungkin ada label atau spasi. Label diakhiri dengan ":" dan dipisahkan dari sisa perintah oleh sejumlah spasi. Baris terdiri dari perintah. Tanda akhir tim adalah simbol ";". Perintah dipisahkan dari argumen oleh spasi. Kasus karakter tidak masalah. Perintah dapat ditulis dengan karakter register apa pun. Selain itu, banyak tim memiliki bentuk singkat. Perintah dapat memiliki kondisi untuk dieksekusi. Jika ada, maka simbol β€œ?” Mengikuti perintah tanpa spasi dan kondisi untuk pelaksanaan perintah ini. Jika kondisi untuk mengeksekusi perintah tidak sama dengan 0, maka perintah dieksekusi. Di dalam kondisi tersebut, spasi tidak diperbolehkan, jika tidak mereka akan diproses sebagai pemisah antara perintah dan argumen.

Sebagai contoh:

SET? [5]> 5 Val [1] = 25; // apakah benar
SET? [2]> 5 Val [1] = 25; // sintaks kesalahan
SET? ([1,2]> 5) Val [1] = 25; // dengan benar, spasi di dalam () diizinkan.

Argumen dipisahkan oleh simbol β€œ,”. Di dalam argumen, spasi bukanlah karakter khusus dan dapat dimuat di mana saja. Biasanya, suatu perintah dapat memiliki sejumlah argumen. Label dalam modul terlokalisasi di dalam modul dan harus unik di dalamnya, dengan pengecualian label di dalam perintah CASE . Label perintah CASE terlokalisasi di dalam perintah ini harus unik hanya di dalam perintah ini dan dapat menduplikasi label di luar perintah ini dan dalam perintah KASUS bersarang .

Runtime


Saat dijalankan, aplikasi memiliki satu tugas atau lebih. Semua tugas dilakukan secara paralel. Dalam setiap tugas, program dijalankan secara berurutan. Pada setiap saat, hanya satu kode program yang dieksekusi dalam tugas. Tugas berakhir dengan akhir dari program yang berjalan terakhir. Tugas utama diluncurkan oleh runtime bahasa. Pekerjaan yang tersisa dihasilkan oleh perintah Job .

Manajemen data


Bagi mereka yang terbiasa dengan bahasa MUMPS, organisasi data dalam MSH cukup jelas. Deskripsi data dalam MSH tidak ada. Tidak ada deklarasi data. Data dapat disimpan sebagai pohon, kemudian akses ke simpul pohon dilakukan dengan nama dan indeks opsional. Indeks terlampir dalam tanda kurung siku []. Nama itu ada di depan mereka.

Sebagai contoh:

SET Pr [4,5, "rt"] = Is ["ty ^ 578"];
Di sini Pr dan Is adalah nama - nama pohon. 4,5, "rt" dan "ty ^ 578" adalah indeks simpul.

Pohon dapat memiliki jumlah level yang berubah-ubah dan, karenanya, indeks memiliki jumlah bidang terkait yang dipisahkan oleh koma. Bidang indeks dapat memiliki nilai arbitrer dari tipe dasar. Tipe dasar dalam MSH adalah angka dan string. Hanya node yang rekamannya dibuat yang langsung disimpan di pohon. Nama, bidang indeks, dan indeks itu sendiri dapat berupa ekspresi. Setelah perhitungan, nama hanya dapat menjadi pengidentifikasi.

Selain itu, data dapat disimpan sebagai array kontinu, kemudian akses ke elemen array terdiri dari nama simbol opsional "$" dan indeks. Indeks adalah bilangan bulat. Indeks array terkecil adalah 1. Nama dan indeks dapat berupa ekspresi. Setelah perhitungan, nama hanya dapat menjadi pengidentifikasi, dan indeks merupakan bilangan bulat. Array dapat diisi dengan urutan apa pun, tetapi jika Anda menulismc $ 1000 , maka array mc dari 1000 elemen akan dibuat . Elemen yang tidak terdefinisi tidak akan mengandung nilai, tetapi mereka akan hadir. Jumlah elemen dalam array dapat ditemukan dengan merujuk pada elemen nol array ini.

Sebagai contoh: mc $ 0
Ukuran array dapat diubah dengan menulis panjang array baru ke elemen ini. Tetapi dalam kasus umum, ini tidak perlu, karena array mengembang secara otomatis.

Node pohon dan elemen array berisi data tipe dasar. Ini adalah string atau angka. Bagaimana data programmer disimpan tidak peduli. Penyimpanan tipe data dan manipulasinya adalah tanggung jawab implementasi bahasa MSH.

Pelokalan data


Data MSH dibagi menjadi global dan lokal. Mereka berbeda dalam jenis nama. Data global disimpan dalam memori jangka panjang dan tidak tergantung pada masa pakai aplikasi. Setelah mereka dibuat, mereka dapat diubah oleh aplikasi dan akan ada sampai aplikasi menghancurkan mereka dengan perintah KILL . Semua data global memiliki awalan β€œ^” dalam namanya.

Akses ke data global secara simultan dimungkinkan dari berbagai tugas. Karena itu, ketika mengakses global, sinkronisasi diperlukan. Sinkronisasi seperti itu selalu otomatis. Selalu ada primitif sinkronisasi di deskriptor global dan itu mengontrol akses ke global. Terlebih lagi, ketika membaca global dihalangi oleh membaca, saat menulis ke global, ia diblokir dengan menulis. Tidak diperlukan sinkronisasi global tambahan. Akses ke array global juga disinkronkan.

Sebagai contoh:

^ gl [87,9] - akses ke simpul pohon global.

^ glar $ 45 - akses ke elemen array global.

Data lokal hanya ada saat aplikasi sedang berjalan. Peluncuran aplikasi berikutnya tidak dapat mengakses data lokal dari peluncuran sebelumnya.

Cakupan data lokal tergantung pada jenisnya. Ada tiga jenis pelokalan data.

1. Data program lokal. Mereka dilokalisasi di dalam program dan ada sejak program diluncurkan hingga selesai. Jika program memanggil subrutin, maka data subrutin baru dibuat, dan data program lokal di dalam subrutin tidak terlihat. Ketika Anda kembali ke program, data program lokal menjadi tersedia lagi. Data program lokal tidak memiliki nama.

Misalnya:

[7,9] - akses ke simpul pohon terlokalisasi di dalam program.

$ 5 - akses ke elemen array yang dilokalkan di dalam program.

Ada satu pengecualian. Array parameter yang diteruskan ke program A $ juga dilokalkan di dalam program.

2. Data aplikasi lokal. Mereka terlihat di semua tugas aplikasi. Anda dapat menghubungi mereka dari tugas apa pun. Mereka ada dari saat mereka dibuat dalam aplikasi oleh tugas apa pun sampai aplikasi selesai atau sampai mereka dihancurkan oleh tim KILL . Nama-nama data tersebut diawali dengan " % ". Variabel-variabel ini secara bersamaan tersedia dalam tugas yang berbeda, sehingga mereka disinkronkan dengan global.

Sebagai contoh:

% dapp [87.9] - akses ke simpul pohon terlokalisasi di dalam aplikasi.

% dapp $ 45 - akses ke elemen array yang dilokalisasi di dalam aplikasi.

3. Data pekerjaan lokal. Mereka dilokalkan di dalam tugas dan ada dari saat mereka dibuat dalam program tugas apa pun sampai tugas selesai atau dihancurkan oleh tim KILL . Data tersebut harus memiliki nama dan tidak mengandung awalan β€œ ^ ” dan β€œ % ”. Pengecualian adalah array parameter program A $ , itu dilokalisasi di dalam program,

misalnya:

djob [87,9] - akses ke simpul pohon terlokalisasi di dalam tugas.
mengisap $ 45 - akses ke elemen array terlokalisasi di dalam pekerjaan.
Akses ke variabel hanya dapat memiliki jenis yang tercantum di sini.

Sintaks singkatan


Istilah ini tidak ada hubungannya dengan istilah serupa dalam bahasa MUMPS. Sintaks yang disingkat dalam MSH digunakan untuk merujuk ke seluruh pohon atau seluruh array. Ini hanya digunakan dalam tim terpisah dan jika diizinkan selalu dinegosiasikan. Banding ke seluruh pohon terdiri dari nama dan tanda kurung yang diperlukan. Tidak ada nama yang ditentukan untuk pohon program lokal.
Sebagai contoh:
us [] - akses ke seluruh pohon as.
[] - akses ke pohon program lokal.

Akses ke seluruh larik terdiri dari nama dan karakter yang diperlukan " $ ". Tidak ada nama yang disediakan untuk array lokal dari program ini.

Sebagai contoh:
us $ - akses ke seluruh array AS.
$ - akses ke array program lokal.

Konstanta


Tipe data dasar dapat berupa numerik atau string. Bentuk numerik adalah bilangan bulat atau bilangan real dengan adanya titik desimal. Basis angka-angka adalah 10. Mereka bisa positif atau negatif.
Sebagai contoh:
25, -4, 789.56, -9.3

String konstanta adalah urutan karakter apa pun. Jika konstanta hanya terdiri dari huruf dan angka, maka Anda tidak dapat melampirkannya dalam tanda kutip, karena tidak dapat dikacaukan dengan variabel. Jika konstanta berisi karakter lain, maka harus diapit dengan tanda kutip tunggal atau ganda.
Misalnya:
"rt @ tty # 123"
'14 "5 * 7" 89 \? '
125Dsv

Fitur dari beberapa tim


Tim KONSTAN


Anda dapat memberikan nama konstan menggunakan perintah KONSTAN . Ini adalah nama waktu siaran. Siaran menggantikannya dengan nilai-nilai mereka. Saat berjalan, nama-nama ini tidak ada lagi. Oleh karena itu, Anda tidak dapat menetapkan ekspresi ke nama dalam perintah KONSTAN . Nilai harus persis konstan. Nama-nama konstanta harus dipilih sehingga tidak sesuai dengan nilai-nilai konstanta yang ditentukan dalam program tanpa tanda kutip.

Misalnya:
Constant ioInOut = "/ini/par.ini>,maxIs=25;
Konstanta ioInOut dan maxI adalah nilai yang ditetapkan. Lebih lanjut dalam program ini nama-nama ini dapat digunakan sebagai pengganti nilai-nilai ini.
Tim KonstanIni memiliki 2 bentuk. Dalam hal ini, sisi kanan kesetaraan tidak ada. Arti tim ini berbeda. Nama adalah nama modul yang berisi konstanta. Konstanta dari modul ini diekspor ke modul saat ini. Konstanta impor modul tidak mengandung deskripsi tambahan tentang impor. Modul impor hanya dapat berisi konstanta dan program.
Sebagai contoh:
CONSTANT sysCnsNet, usrCnsByx;
sysCnsNet dan usrCnsByx adalah nama modul yang mengandung konstanta.
Kedua bentuk dapat muncul sebagai argumen untuk satu perintah KONSTAN .

Tim XECUTE


Perintah XECUTE adalah tim yang agak eksotis, tetapi hadir dalam bahasa MUMPS. Dalam bahasa pemrograman lain, dia hanya bertemu saya di JavaScript. Itu disebut eval. Ketika perintah ini dieksekusi, ekspresi argumen dari perintah ini dihitung, dan kemudian ekspresi ini dikonversi ke string, ditafsirkan sebagai perintah MSH, dan dieksekusi.

Misalnya:
XECUTE "SET $ 1 = 89;";
Akibatnya, variabel $ 1 akan menerima nilai 89 .
Ini adalah contoh primitif, dalam bentuk ini hampir tidak masuk akal untuk menggunakan perintah ini. Argumen untuk perintah XECUTE adalah ekspresi, yang memungkinkan Anda untuk menghasilkan berbagai perintah MSH pada saat program berjalan .
Perintah dieksekusi dalam konteks program di mana perintah berada. Semua sumber daya program tersedia baginya, termasuk data program lokal.

Perintah COPY dan MOVE


The Perintah COPY adalah mirip dengan MERGE gondok perintah . Perintah-perintah ini menyalin simpul sumber bersama dengan semua keturunan ke simpul penerima. Argumen dari perintah ini terdiri dari dua bidang yang dipisahkan oleh simbol " = ". Di sebelah kanan tanda ini adalah simpul sumber, penerima di sebelah kiri. Tautan yang disingkat diizinkan sebagai simpul, dalam hal ini seluruh pohon digunakan. Perintah-perintah ini tidak hanya menyalin keturunan, tetapi juga node itu sendiri. The perintah COPY penggabungan Melakukan data. Sumber data disalin ke penerima tanpa membersihkannya. Sumber tidak berubah. Tim MOVEmelakukan pemindahan data yang sebenarnya. Sebelumnya, penerima dibersihkan, maka semua turunan dari simpul sumber disalin dan simpul sumber dihapus dengan semua turunannya.

Sebagai contoh:
// node us [5,6] disalin ke node [1]
COPY [1] = us [5,6];
// pohon us keseluruhan dipindahkan ke simpul [8]
MOVE [8] = us [];
Perintah-perintah ini juga dapat digunakan untuk menyalin array. Dalam hal ini, hanya tautan singkat yang dapat digunakan sebagai sumber dan penerima.
Argumen program disalin ke array arg.
COPY arg $ = A $;
Anda dapat menggunakan perintah MOVE untuk bergerak.
PINDAH a1 $ = b1 $;
Anda dapat menyalin dan memindahkan array apa pun.

Sinkronisasi Sumber Daya


Ketika melakukan beberapa tugas, penting untuk mengakses sumber daya bersama. Sinkronisasi dilakukan dengan perintah kunci. Perintah sinkronisasi sendiri tidak memblokir apa pun, ini adalah serangkaian perjanjian yang memungkinkan untuk membedakan akses ke sumber daya bersama. Jika perintah kunci tidak dibagi di semua pekerjaan, sinkronisasi akses tidak akan terjadi. Sinkronisasi dibuat berdasarkan nama kunci. Nama-nama ini dilokalkan dalam aplikasi dan sama untuk semua tugas. Dalam kunci, konsep banyak pembaca dan hanya satu penulis pada suatu waktu diterima. Dengan demikian, ada kunci baca dan tulis kunci.

Tim LockRblok nama pembacaan. Nama-nama yang tercantum dalam argumennya akan diblokir dengan membaca. Sejumlah tugas dapat memblokir nama yang sama, tetapi tugas yang mencoba memblokir salah satu dari nama-nama ini akan menunggu semua nama ini dibuka. Setelah mendapatkan nama tulis, tidak ada perintah baca kunci yang dapat dijalankan sampai kunci tulis melepaskan nama. Jika tidak memungkinkan untuk mengunci, perintah akan menunggu nama untuk dirilis.

Misalnya:
LockR name1, name2, name3;
Nama-nama ini akan diblokir dengan membaca. Tugas lain juga dapat mengunci nama-nama ini tanpa menunggu mereka untuk dibuka. LockW

perintahmemblokir nama berdasarkan catatan. Nama-nama yang tercantum dalam argumennya akan diblokir oleh catatan. Jika nama yang tercantum dalam argumen sudah diblokir oleh perintah kunci apa pun, maka perintah ini akan menunggu rilis nama-nama ini.
Misalnya:
LockW name1, name2, name3;
Nama-nama ini akan dikunci oleh catatan.
Perintah LockUn membuka kunci nama ini. Jika nama diblokir dengan membaca beberapa kali, maka Anda perlu membuka kunci beberapa kali yang sama.
Misalnya:
LockUn name1, name2, name3;
Fungsi standar memiliki analog dari perintah ini dengan batas waktu.

Bentuk pendek dari perintah SET


Perintah SET memiliki bentuk yang disingkat. Dalam hal ini, sisi kiri dari kesetaraan tidak ada, perannya dimainkan oleh variabel terakhir yang disebutkan dalam ekspresi.
Misalnya:
SET $ 1 = 2, $ 1 + 3;
Variabel $ 1 akan menjadi sama dengan 5 .
Jika ada beberapa variabel dalam ekspresi, hasilnya akan ditetapkan ke variabel terakhir.

Sebagai contoh:
SET $ 1 = 1, $ 2 = 2, $ 3 = 3, $ 1 + $ 2 + $ 3;
Variabel $ 3 akan menjadi 1 + 2 + 3 = 6. Meskipun formulir ini lebih tepat digunakan hanya dalam kasus yang sangat sederhana, mirip dengan contoh pertama. Contoh kedua disediakan hanya sebagai ilustrasi kemampuan bentuk perintah SET ini .

Memblokir tim


Perintah blok membentuk blok perintah dan sekaligus berfungsi sebagai judul blok. Setiap perintah blok harus memiliki perintah END sendiri , bahkan jika hanya ada satu perintah di blok.

JIKA tim


Perintah IF membentuk blok yang dieksekusi jika kondisi untuk mengeksekusi perintah ini benar. Perintah ini tidak memiliki argumen. Blok ini dapat berisi perintah ELSE . Perintah ELSE tidak memiliki argumen. Di luar blok IF , perintah-perintah ini tidak memiliki arti dan tidak dapat diterapkan. Jika ada perintah ELSE di blok IF ketika kondisi perintah IF terpenuhi, hanya perintah di belakang perintah IF yang dieksekusi sampai perintah ELSE berikutnya . Tim ELSEdapat berisi kondisi eksekusi, maka dalam kasus kebenaran dalam kondisi ini hanya perintah yang terletak setelah perintah ini akan dieksekusi sampai perintah ELSE berikutnya atau perintah END . Blok IF hanya bisa berisi satu perintah ELSE tanpa syarat untuk pelaksanaannya, dan itu harus menjadi yang terakhir di antara perintah ELSE .

Misalnya:
JIKA? [6] <0;
SET y [1] = 1;
LAIN? [6] <5;
SET y [1] = 2;
LAIN? [6] <10;
SET y [1] = 3;
LAIN SET y [1] = 4;
AKHIR
Kondisi untuk pelaksanaan perintah ini mungkin tidak ada, maka blok ini akan dieksekusi dalam hal apa pun. Walaupun sulit membayangkan mengapa ini bisa bermanfaat.

Tim KASUS


Semantik dari perintah ini agak berbeda dari semantik tim MSH lainnya. Kondisi untuk mengeksekusi perintah di dalamnya tidak seperti itu. Dalam kondisi pelaksanaan perintah CASE , ekspresi harus menghitung label yang kontrolnya akan ditransfer. Perintah ini tidak memiliki argumen.

Setiap label dalam perintah ini membentuk blok dari label ini ke yang berikutnya. Ketika kontrol ditransfer ke label, hanya perintah yang dijalankan sampai label berikutnya, dan kemudian blok CASE saat ini keluar . Perintah ini lebih dekat ke notasi Pascal daripada ke perintah C switch. Jika sebagai hasil dari penghitungan nama label, ditemukan nama yang tidak ada di blok CASE saat ini, perintah yang berada setelah perintah CASE sebelum label pertama akan dieksekusi .

KASUS? L_ $ J; // label dievaluasi
SET x [1] = 1; // jika tidak ada label yang ditemukan maka perintah dari blok ini dijalankan
SET a [2] = x [1] +1;
L1: SET x [1] = 2; // label command block L1
SET a [2] = x [1] +2;
L2: SET x [1] = 3; // label command block L2
SET a [2] = x [1] +3;
AKHIR
Label dalam perintah ini secara implisit membentuk blok perintah internal. Setelah eksekusi blok perintah seperti itu, kontrol ditransfer di luar blok perintah CASE .

Perintah SAAT


Perintah WHILE digunakan untuk mengatur loop. Kondisi untuk pelaksanaan perintah ini menetapkan kondisi untuk kelanjutan dari loop. Selama kondisi untuk mengeksekusi perintah bukan 0, blok yang dibentuk oleh perintah ini akan dieksekusi. Blokir diakhiri dengan perintah END . Perintah END dari blok semacam itu memiliki fitur. Ini mungkin memiliki kondisi penghentian blok. Jika kondisinya bukan 0, maka blok akan selesai. Selain itu, kondisi ini dapat hadir baik di perintah WHILE dan di perintah END .
Misalnya:
WHILE? X [7]> 0; // kondisi untuk melanjutkan siklus
SET y [2] = x [7] +2;
BREAK? Y [2] <0;
SET x [7] = x [7] +1;
AKHIR? X [7]> 20; // kondisi untuk mengakhiri loop
Di dalam blok, loop dapat terputus oleh perintah BREAK.

Blokir iterator loop


Iterator loop loop dioptimalkan untuk akses ke simpul pohon. Mereka menggunakan tautan internal untuk mengoptimalkan akses ke bypass node. Ini memberlakukan pembatasan pada penggunaan iterator blok. Di dalam blok Anda tidak dapat mengubah struktur pohon. Anda tidak dapat menulis ke pohon ini. Dalam perintah iterator blok loop, 2 argumen.
Argumen pertama diperlukan, tautan ke simpul yang keturunannya akan dilewati. Indeks referensi. Tautan yang diperpendek dapat digunakan. Argumen kedua adalah tautan ke simpul tempat indeks turunan akan disimpan. Argumen ini opsional. Di dalam blok, argumen 2 seharusnya tidak berubah. Ekspresi seperti $$ 2 atau [[3]] tidak diperbolehkan jika $ 2 atau [3]ubah di dalam blok iterator. Perubahan pada variabel-variabel ini tidak akan diperhitungkan. Akses ke indeks anak dapat diperoleh melalui variabel sistem % queryKey , dan data node dari properti% queryData . Jika keturunan tidak boleh dilewati sejak awal, maka argumen ke-2 diperlukan dan indeks simpul harus ditempatkan di dalamnya setelah itu bypass keturunan dimulai. Jika ada argumen kedua, tetapi Anda harus berkeliling dari awal, maka sebelum loop Anda perlu menghapus variabel ini dengan perintah KILL .
Perintah dapat memiliki kondisi eksekusi blok. Kondisi ini diperiksa hanya sekali setelah memasuki blok.

Anda dapat berkeliling tidak hanya simpul pohon, tetapi juga array. Dalam hal ini, nomor seri bidang array masuk ke argumen kedua. Hanya tautan singkat yang dapat digunakan sebagai argumen pertama.

Tim BERIKUTNYA


Perintah NEXT beriterasi pada keturunan langsung dari simpul pohon. Keturunan biaya dalam arah maju dari minimum ke indeks maksimum.
Sebagai contoh:
BERIKUTNYA kami [4,5]; // 2 argumen tidak ditentukan, indeks diambil
// dari variabel sistem% queryKey
SET $ 1 =% queryKey, $ 2 =% queryData;
AKHIR? $ 1> 1000; // kondisi untuk mengakhiri loop
Indeks node segera ditempatkan dalam data
KILL $ 1;
NEXT us [4,5], $ 1;
SET $ 2 =% queryData;
AKHIR

Tautan yang disingkat digunakan sebagai simpul referensi. Dalam hal ini, tingkat pertama pohon dilewati.
Bunuh $ 1;
NEXT us [], $ 1;
SET $ 2 =% queryData;
AKHIR
Perayapan setelah indeks 3.
SET $ 1 = 3;
NEXT us [4,5], $ 1;
SET $ 2 =% queryData;
AKHIR
Saat melintasi array, semua bidang bahkan berurutan, bahkan bidang yang datanya tidak ditentukan.
Misalnya:
BUNUH $ 1;
NEXT us $, $ 1;
SET $ 2 =% queryData;
AKHIR
Di dalam blok, loop dapat terputus oleh perintah BREAK .

KEMBALI tim


Perintah BACK berbeda dari perintah NEXT hanya dalam arah traversal dari vertex terakhir ke yang pertama.
Misalnya:
BUNUH $ 1;
BACK us [4,5], $ 1;
SET $ 2 =% queryData;
AKHIR

Tim QUERY


Perintah QUERY melintasi semua turunan node dari kiri ke kanan dan dari atas ke bawah ke kedalaman penuh di arah maju. Argumen ke-2 berisi seluruh indeks opsional. Jika indeks ini memiliki lebih dari 1 bidang, maka daftar ditempatkan di argumen ke-2.

Jika tidak, perintah ini mirip dengan perintah NEXT .

Perintah QUERY melintasi array hanya ke arah maju dari kiri ke kanan.

Misalnya:
BUNUH $ 1;
QUERY us [4,5], $ 1;
SET $ 2 =% queryData;
AKHIR
Tetapi perintah ini hanya memintas simpul yang penting.

Perintah Perintah Blok Data Pohon Non Blok


Dalam perintah ini, kedua argumen perintah diperlukan. Argumen kedua menyimpan indeks, setelah itu perintah selanjutnya akan menemukan titik berikutnya. Dalam perintah ini tautan internal tidak disimpan dan oleh karena itu tidak ada batasan untuk menyesuaikan pohon yang dilewati. Untuk alasan yang sama, waktu akses ke puncak bisa lebih lama. Array juga dapat dilewati dengan perintah-perintah ini.

Command NEXT1

perintah NEXT1 memberikan node berikutnya pada level yang sama di bawah node referensi.
Data node tersedia dalam variabel sistem % queryData .
Sebagai contoh:
SET $ 1 = 2;
NEXT1 us [1,4], $ 1;
// akan memberikan simpul yang terletak di level 3 setelah simpul kita [1,4,2]

Tim BACK1


Perintah BACK1 memberikan simpul sebelumnya pada tingkat yang sama di bawah simpul referensi.
Kalau tidak, ini mirip dengan perintah NEXT1 .

Tim QUERY1


Perintah QUERY1 memberikan simpul berikutnya dari cabang pohon sambil melintasi seluruh simpul dari atas ke bawah dan dari kiri ke kanan. Argumen ke-2 berisi seluruh indeks opsional. Jika indeks ini memiliki lebih dari 1 bidang, maka daftar ditempatkan di argumen ke-2.

Kalau tidak, ini mirip dengan perintah NEXT1 .

Manajemen Program


Label modul dapat menjadi titik panggilan untuk suatu program, fungsi, titik panggilan untuk tugas baru, properti objek, metode objek, dan label, tergantung pada akses ke label ini.
Selain itu, label dapat diakses secara berbeda di berbagai bagian modul.
Misalnya:
LB: Set Val [25] = 7 + A $ 1; Return Val [25];
Do LB (78); // Akses ke program. Nilai pengembalian diabaikan.
Set Val [7] = 8 * LB (6); // Memanggil sebagai fungsi, nilai pengembalian digunakan.
JOB LB (17, β€œyt”); // panggil pekerjaan baru
Set Val [9] = Mod.LB (3); // Akses ke metode kelas Mod- nama modul dalam konteks ini diperlakukan sebagai nama kelas objek.
Set Val [15] = Obj [1,2, A] .LB; // Akses ke properti LB objek Obj [1,2, A],
Go LB; // Pergi ke label LB
Dalam contoh di atas, selain 4 dan 5, panggilan dilakukan di dalam modul saat ini. Panggilan program dan fungsi dapat dilakukan ke modul yang tersedia. Omong-omong, ini juga berlaku untuk tim Go.
Misalnya, dalam modul Mod ada label Lb. Maka daya tarik itu akan terlihat seperti:
Do Mod.Lb (78);
Set Val [7] = 8 * Mod.Lb (6);
Set Val [9] = Mod.Lb (3);
JOB Mod.Lb (78);
Go Mod.Lb;

Secara umum, label digunakan sebagai program atau fungsi. Jika modul digunakan sebagai kelas objek, labelnya adalah properti atau metode objek ini. Properti suatu objek dan metodenya adalah bentuk lain dari akses ke program dan fungsi, jadi semua yang dikatakan tentang program dan fungsi berlaku sama untuk properti dan metode. Tidak ada nuansa yang berarti ketika mengakses objek hanya dalam hal pewarisan. Masalah ini akan dijelaskan secara lebih rinci di bawah ini.

Dalam kasus umum, nama modul dan nama label yang dipanggil adalah ekspresi dan dapat dihitung pada saat panggilan.
Sebagai contoh:
Set $ ​​1 = β€œMdβ€œ, $ 2 = β€œLbβ€œ;
Lakukan $ 1. $ 2;

Program berakhir dengan perintah Kembali; Modul dapat diselesaikan dengan perintah Akhir;

Melewati parameter


Dalam MSH, parameter dilewatkan hanya oleh nilai. Secara umum, tidak ada referensi dan petunjuk dalam hal bahasa C ++ dan masalah besar yang terkait dengan penggunaannya di sini, pada prinsipnya, tidak ada. Sebuah program selalu mengambil jumlah sewenang-wenang parameter dalam A $ array yang . Angka mereka dapat ditemukan dengan merujuk pada elemen 0 array A $ 0 . Programmer bertanggung jawab atas arti dari parameter-parameter ini.

Sebagai contoh:
Kami memiliki program Lb. Ini dapat diatasi:
DO Lb (1,2,7);
DO Lb (25.7);
DO Lb ();
JOB Lb (8);
SET [7.8] = Lb (187, β€œPrivet”);

Parameter yang tidak lulus dalam program tidak ditentukan.
Melewati parameter dengan nilai tidak mengganggu memasukkan nama variabel ke dalam program dan menggunakannya di sana.
Misalnya:
Tetapkan kami [5] = 48;
Do Lb ("us");
...
Kembali;
Lb: Set par [8,1,9] = A $ 1 [5];
// A $ 1 - parameter pertama yang dikirimkan berisi nama
variabel //: us .
// [5] - akses ke atas pohon ini
// sebagai hasilnya, node menghargai kita [5] = 48
Return;
Akibatnya, nama variabel dapat dimanipulasi secara sewenang-wenang.
Saat membuka label dengan perintah GO, array parameter tidak berubah. MSH memiliki formulir perintah GO dengan transfer parameter baru. Dalam hal ini, array parameter saat ini diganti dengan yang baru yang ditentukan dalam panggilan perintah GO .
Misalnya:
GO Lb (1,2,7);

Penanganan acara


Pemrosesan acara adalah mekanisme pemrograman yang kuat yang biasanya tidak termasuk dalam bahasa tingkat tinggi. Tetapi kehadirannya di perpustakaan dan sistem operasi berbicara tentang pentingnya. Perpustakaan komponen visual dibangun berdasarkan mekanisme ini. Kehadiran pemrosesan acara dalam bahasa memperluas kemampuan bahasa. Membuka gaya pemrograman berbasis acara baru. Omong-omong, bahasa pemrograman seperti Assembler memiliki fitur-fitur seperti itu. Oleh karena itu, mekanisme ini telah ditambahkan ke bahasa MSH.

Dasar dari mekanisme ini adalah acara tersebut. Itu dilokalisasi di dalam aplikasi. Dengan demikian, nama-nama ini harus unik di seluruh aplikasi. Jika nama acara cocok dengan nama yang dinyatakan dalam perintah KONSTAN, maka nama acara akan diganti dengan nilai konstanta yang dinyatakan. Hati-hati. Saat memberi nama acara, disarankan untuk mematuhi beberapa jenis strategi penamaan. Misalnya, tetapkan nama acara yang dimulai dengan evu . Panjang nama, dengan mempertimbangkan pengkodean UTF8, tidak boleh melebihi 18 byte. Batasan ini hanya dikaitkan dengan implementasi bahasa saat ini.

Suatu peristiwa yang dibuat dalam satu tugas terlihat dan dapat diproses dalam tugas apa pun. Penangan acara dapat berupa nomor berapa pun dan mereka dapat melakukan tugas yang berbeda.
Setelah peristiwa itu terjadi, diperiksa apakah ada penangan untuk acara ini, jika tidak ada penangan, acara tersebut dihapus. Jika ada penangan, maka mereka dieksekusi berurutan. Acara dapat berupa sistem dan pengguna. Peristiwa sistem dihasilkan oleh sistem. Acara kustom dihasilkan oleh perintah EVENTTRAP . Acara melewati parameter ke penangan, seperti saat menjalankan program. Setelah diproses, penangan acara tidak dihapus. Untuk menghapus suatu peristiwa, gunakan perintah EVENTDELETE . Suatu peristiwa dapat ditangani oleh perintah EVENTCALL dan EVENTWAIT .

Tim EVENTTRAP


Perintah menciptakan acara khusus. Format perintah menyerupai panggilan program, hanya nama acara yang digunakan, bukan nama program. Nama acara bersifat lokal di dalam aplikasi, sehingga dapat terlihat di semua tugas.

Tim akan membuat acara dengan nama yang ditentukan. Penangan acara akan melewati parameter yang tercantum dalam argumen perintah.

Misalnya:
EVENTTRAP? X [1]> 8 evuBoxData (us [7], $ 4), evuKorXY (us [X], us [Y], sh);
2 event evuBoxData dan evuKorXY dihasilkan sebagai variabel kita [7], $ 4, us [X], us [Y] dan string konstan sh .
Jika saat ini tidak ada penangan untuk acara ini, maka acara tersebut tidak dihasilkan.

Tim EVENTDELETE


Perintah menghapus penangan acara yang tercantum dalam argumen program.
Misalnya:
EVENTDELETE? X [1]> 7 evuKorXY, evuBoxData;
Acara akan dihapus sesuai urutan dalam tim.

Tim EVENTCALL


Perintah ini menetapkan pengendali event. Pawang adalah sebuah program. Program ini akan dipanggil secara asinkron dari tugas yang sedang berjalan dan parameter akan diteruskan ke sana. Setelah pelaksanaan program handler, kontrol akan dikembalikan ke tugas utama di situs interupsi.

Sebagai contoh:
EVENTCALL evuBoxData = Mod1.intEvuBoxData, evuKorXY = Mod2.intevuKorXY;

Tim EVENTWAIT


Tim sedang menunggu acara terjadi. Perintah ini akan memblokir tugas saat ini hingga peristiwa yang tercantum dalam argumennya terjadi. Semua peristiwa yang tercantum dalam argumennya harus terjadi untuk melanjutkan eksekusi utas saat ini. Parameter program saat ini diganti oleh yang ditransfer dalam perintah pembuatan acara.
Misalnya:
EVENTWAIT evuBoxData, evuKorXY;
Perintah-perintah ini memungkinkan Anda untuk mengatur eksekusi program yang tidak sinkron.

Vektor


Vektor terkait erat dengan implementasi saat ini. Mereka menyimpan bilangan bulat yang ditandatangani dan tidak ditandatangani. Dimensi dari vektor-vektor ini tergantung pada kedalaman bit dari komponen vektor dan itu diperbaiki.

64 bit vektor


Dimensi dari vektor tersebut adalah 2. Komponen dapat berupa bilangan bulat 64-bit atau bilangan bulat yang tidak ditandatangani. Angka-angka tersebut disimpan dalam variabel apa pun.
Daya tarik untuk komponen integer ikonik dari vektor.
SET kami [5].% V64 (0) = ss $ 1.% v64 (1);
% v64 - akses ke komponen bertanda integer vektor.
Menarik untuk komponen integer yang tidak ditandatangani dari suatu vektor.
SET kami [5].% Vu64 (0) = ss $ 1.% vu64 (1);
% vu64 - akses ke seluruh komponen vektor yang tidak ditandatangani.

Vektor 32 bit


Dimensi dari vektor tersebut adalah 5. Komponen dapat berupa bilangan bulat 32-bit atau bilangan bulat tanpa tanda. Angka-angka tersebut disimpan dalam variabel apa pun.
Daya tarik untuk komponen integer ikonik dari vektor.
SET kami [5].% V32 (0) = ss $ 1.% v32 (4);
% v32 - akses ke komponen bertanda integer vektor.
Menarik untuk komponen integer yang tidak ditandatangani dari suatu vektor.
SET kami [5].% Vu32 (0) = ss $ 1.% vu32 (4);
% vu32 - akses ke seluruh komponen vektor yang tidak ditandatangani.

16 bit vektor


Dimensi dari vektor tersebut adalah 11. Komponen dapat bilangan bulat atau tidak bertanda 16-bit. Angka-angka tersebut disimpan dalam variabel apa pun.
Daya tarik untuk komponen integer ikonik dari vektor.
SET kami [5].% V16 (0) = ss $ 1.% v16 (10);
% v16 - akses ke komponen bertanda integer vektor.
Menarik untuk komponen integer yang tidak ditandatangani dari suatu vektor.
SET kami [5].% Vu16 (0) = ss $ 1.% vu16 (4);
% vu16 - akses ke komponen integer yang tidak ditandatangani dari vektor.

Vektor 8 bit


Dimensi dari vektor tersebut adalah 22. Komponen dapat berupa bilangan bulat 8-bit atau bilangan bulat. Angka-angka tersebut disimpan dalam variabel apa pun.
Daya tarik untuk komponen integer ikonik dari vektor.
SET kami [5].% V8 (0) = ss $ 1.% v8 (21);
% v8 - akses ke komponen bertanda integer vektor.
Menarik untuk komponen integer yang tidak ditandatangani dari suatu vektor.
SET kami [5].% Vu8 (0) = ss $ 1.% vu8 (21);
% vu8 - akses ke seluruh komponen vektor yang tidak ditandatangani.

Operasi


Operasi di MSH memainkan peran khusus. Merekalah yang mengontrol konversi tipe data. Tergantung pada operasinya, operan dilemparkan ke tipe data yang diinginkan. Jenis hasil data secara unik sesuai dengan jenis operasi. Operasi string dan numerik tidak tumpang tindih, seperti operasi + dalam bahasa mirip C. Jenis operasi di MSH tidak tergantung pada jenis operan, semuanya justru sebaliknya. Tidak ada prioritas operasi di MSH, ini adalah warisan historis MUMPS.

Sebagai contoh:
SET $ 1 = 2 + 3 * 4;
$ 1 akan menjadi 20, bukan 14.
Agar hasilnya menjadi 14, tanda kurung digunakan.
SET $ 1 = 2 + (3 * 4);
Sebagai operasi penggabungan string, simbol " _ " digunakan.
Kurangnya prioritas operasi tidak biasa, tetapi cukup nyaman. Referensi kealamian prioritas, ketika operasi lebih dari menjumlahkan menjadi sangat diragukan. Setelah mengetahui bahwa tidak ada prioritas, tidak perlu mengingat prioritas mereka dengan menyakitkan, dan jika sesuatu masuk ke dalam dokumentasi. Secara umum, ini masalah kebiasaan.

Benda-benda


Kehadiran objek dalam bahasa pemrograman modern adalah bentuk yang baik. Dalam kasus umum, objek terdiri dari 2 bagian. Bagian dari deskripsi deklaratif dan bagian dari implementasi. Dalam sistem MUMPS, variabel tidak memiliki bagian deklaratif dari deklarasi tipe. Kelas pada dasarnya adalah tipe data pengguna. Agar tidak melanggar prinsip-prinsip MUMPS, MSH tidak memiliki bagian deklaratif dari deskripsi kelas. Dan ternyata, Anda bisa melakukannya tanpanya dengan sempurna. Hanya sebagian dari implementasi yang tersisa dari kelas. Implementasi kelas dapat diwakili dengan sempurna oleh modul standar. Hanya untuk kelas yang harus memperkenalkan konvensi tambahan yang terkait dengan deskripsi properti objek. Objek hanya bisa di pohon. Menempatkan objek dalam array akan gagal karena tidak ada tempat untuk menyimpan properti objek. Walaupun jika objek tidak memiliki properti, maka Anda bisa mencoba.Meskipun objek macam apa itu.
Untuk menjelaskan properti publik, Anda memerlukan fungsi yang mengembalikan nilai properti ini. Itu harus memiliki nama properti dan berada di modul dengan nama kelas. Program untuk menulis ke properti. Program ini memiliki nama properti yang diawali dengan "." Dan program penghapusan properti. Program ini memiliki nama properti yang diawali dengan "..".

Nama fungsi dalam modul dapat sesuai dengan properti publik untuk dibaca. Dalam hal ini, nilai pengembalian fungsi tersebut diteruskan ke program panggilan sebagai nilai dari properti publik.

Konstruktor kelas adalah metode data% objNew. Jika, ketika membuat objek, perlu untuk menentukan properti atau memperoleh sumber daya, maka program modul kelas apa pun (metode kelas) dapat digunakan. Tetapi disarankan untuk mematuhi setiap strategi penamaan kelas konstruktor. Misalnya, nama konstruktor harus sesuai dengan nama kelas.

Akses ke properti yang dilindungi dari kelas dilakukan melalui properti sistem % ini .

Destructor adalah penghapusan objek menggunakan perintah KILLD. Jika Anda perlu membebaskan sumber daya apa pun atau melakukan manipulasi tambahan, maka ini dapat dilakukan oleh program apa pun dari kelas ini (metode kelas). Seperti dalam kasus konstruktor, disarankan untuk mematuhi beberapa strategi penamaan saat penamaan destruktor.

Sebagai contoh:
// Orang Kelas
// Umur Properti
// baca milik umum Umur
Umur: RETURN [% this, Age];
// catatan dari properti umum Age
.Age: SET [% this, Age] = A $ 1;
Kembali
AKHIR

Banding dari program ke objek dan properti publik akan terlihat sebagai berikut.
// buat objek Orang
Setel kami [1,2].% objNew = Orang;
// tulis nilai 50 ke properti Age.
Atur kami [1,2]. Agge = 50;
// baca properti Age
SET u $ 1 = us [1,2] .Age + 5;
// hapus properti Umur
MEMBUNUH kami [1,2] .Baru;

Objek Warisan


Kelas MSH mendukung multiple inheritance. Perintah PARENT mengatur semua leluhur dari kelas ini. Selain itu, urutan nama-nama leluhur kelas ini dalam argumen perintah menentukan prioritas warisan. Semakin belakangan kelas disebutkan, semakin rendah prioritasnya.

Misalnya:
PENGGUNA ORANGTUA, KOTAK;
Kelas mewarisi dari nenek moyang USER dan BOX . Prioritas leluhur USER lebih tinggi. Apa prioritasnya? Saat mengakses objek, properti umum atau metode kelas akan dicari di kelas itu sendiri, jika mereka tidak ditemukan di sana, mereka akan dicari pada leluhur dengan prioritas tertinggi, dan kemudian pada leluhur kelas ini dan seterusnya berdasarkan prioritas.

File sharing

Dalam MSH, berbagi file diatur pada tingkat yang paling primitif. File di MSH memainkan peran pendukung. Pertukaran hanya diatur dengan file teks. Struktur file adalah bidang teks yang dipisahkan oleh pemisah yang ditentukan. Pembatas dalam variabel sistem % dlmIO . Secara default, variabel ini adalah " , ". Ini tersedia untuk membaca dan menulis. Saat menulis ke file, variabel dikonversi ke tipe string dan ditulis ke file melalui pembatas. Saat membaca dari file, variabel dipilih melalui pemisah dan dibawa ke bentuk normal. Jika bidang adalah catatan angka, maka angka ditempatkan dalam variabel. Pertukaran dengan file terjadi melalui array B $ . Saat menulis, array adalah B $ditulis ke file melalui pembatas. Saat membaca dari file, bidang dipilih ke dalam array B $ .

Perintah pertukaran file menggunakan path file sebagai argumen.
Sebagai contoh:
Dari array data $ B ditulis ke file. File dibuka dengan tulisan. Data dalam file diganti.
Tulis "txt / tt1.txt";
Data dibaca ke dalam array B $ . Array sudah dihapus.
Baca "txt / tt1.txt";
txt / tt1.txt - path ke file.

Kesimpulan


Dokumen ini bukan pengganti untuk deskripsi bahasa MSH, tetapi hanya melengkapi saja. Di sini, tidak semua fitur bahasa MSH dipertimbangkan, tetapi hanya fitur yang ingin saya tarik perhatian Anda.

Penulis: Sharymov Mikhail Alekseevich. Email: misha_shar53@mail.ru

Saat menggunakan materi ini, tautan ke sumber dan penulis diperlukan.

All Articles