MUMPSからMSHへ

前回の記事で、MUMPSのようなあまり知られていないプログラミング言語のメリットについて人々に伝えようとしました。 しかし、その利点に加えて、この記事で共有したい欠点もあります。 方法でこの言語を見て気にしたいくつかの解説者は、彼らに注意を引きました。 さらに、新しいMSH言語でこれらの欠点に対処する方法を提案したいと思います。

MUMPS言語の第一印象は、古風なものだということです。 それはずっと前に作成され、標準で修正されており、第2版と比較してほとんど変更されていません。 MUMPSコミュニティでは、この言語の変更をかなり強く拒否しています。 しかし、実装では、欠点を補うために拡張機能を導入しようとしますが、非常に失敗することもあります。 しかし、その欠陥にもかかわらず、MUMPSイデオロギーは非常に生産的です。
概して、この言語の主な欠点は、オブジェクトとイベント処理システムの欠如です。 オブジェクト指向ではありません。 まず、理由は、いつものように、その歴史にあります。 作成時には、オブジェクトプログラミングは一般的ではありませんでした。 この言語はすぐに標準化されたため、根本的な変更はできませんでした。 第二に、言語にオブジェクトを含めることは、言語に変数宣言がないために防止されます。
つまり、オブジェクトを言語に追加する必要があります。 さらに、現代の高級プログラミング言語には、必ず高度なイベント処理システムが含まれている必要があると思います。 私が知っているすべての言語のうち、イベント処理機能を持つのはアセンブラーだけです。 イベント処理方法論は、ビジュアルライブラリ(Delphi、GTKなど)とオペレーティングシステムの構築の両方で、プログラミングの実践で広く使用されています。 ライブラリレベルのオペレーティングシステムには、さまざまなイベント処理機能があります。 MUMPSのイベント処理は非常に未開発であり、実際にはエラー処理になりますが、ZTRAPコマンドはカスタムイベントを作成できます。
MSH言語を作成するための出発点として、私は偶然ではなくMUMPSを取りました。 これは完璧な言語です。 ある意味で理想的です。 矛盾や不必要な構造はありません。 組み込み言語機能の小さいながらも強力なライブラリ。 信じられないほどの言語の柔軟性。
この言語の主な、しかし唯一の利点は、データの編成と管理です。 データの説明がありません。 したがって、コンテキストに応じて、変数はさまざまな形式で表示できます。 あるコンテキストでは、文字列として解釈され、別のコンテキストでは数値と​​して解釈されます。 変数の構造はツリーですが、変数は単純な場合があります。 変数は、別の大陸であっても、RAMと任意のブロックデバイスの両方に配置できます。
RAMと外部メディアの両方でのデータの表示はほぼ同じであるため、データは同じサブジェクトを使用して同じ言語で処理できます。 この言語には、データの整合性を確保するためのシステムが開発されています。 つまり、完全に機能する分散データベースです。 特定の実装には、ジャーナリングおよびデータ複製システムもあります。 この言語には、同期ツールを備えたマルチタスクが組み込まれています。 間接構文とXecuteコマンドを使用すると、プログラムの外部からの外部コマンドを処理できます。

最初の欠陥は非常に簡単に除去されます。 言語には宣言性が基本的にないため、オブジェクトの説明の宣言部分は破棄され、標準モジュールの形式でのオブジェクトの実装のみが残ります。 また、オブジェクトのプロパティにアクセスするために、ポイント構文が言語に追加されます。 オブジェクトのパブリックプロパティの名前は、モジュールのエントリポイントに関連付けられています。 継承を整理するために、引数にこのクラスのすべての祖先をリストする追加のExtendコマンドを導入します。
ただし、イベント処理システムは完全に開発する必要があります。 これを行うために、イベント処理コマンドがMSH言語に追加されました。

1. EventCall-コマンドは処理プログラムをイベントに添付します。
2. EventWait-チームは、指定されたイベントの発生を待機しています。
3. EventDelete-コマンドはイベントを削除し、
4. EventTrap-コマンドはイベントを発生させます。

これらのコマンドはイベントを処理するのに十分なはずです。 イベントは全身的である可能性があり、これらは外部環境によって生成されるものです。 たとえば、デバイスを非同期で開くか、プログラムで実行時エラーが発生します。 イベントは、EventTrapコマンドを使用してアプリケーションで生成することもできます。これはカスタムイベントです。 必要なパラメーターは、引数としてイベントプロセッサに渡されます。

MUMPSと比較したMSH言語の他の変更はそれほど基本的ではありませんが、それでもその機能を改善する必要があります。
データのローカライズから始めましょう。 MUMPSには、データスコープを指定するための独自の用語があります。 他のプログラミング言語のMUMPSグローバルの類似物は、データベースにあるデータです。 C言語のMUMPSロケールの類似物は、グローバル変数および自動変数です。 デフォルトでは、すべてのMUMPS変数はC言語の用語ではグローバル変数です。 MUMPSのC用語で自動変数を作成するには、2つの形式の新しいコマンドがあります。 最初の形式は、C言語での変数の宣言にほぼ対応しています。 このコマンドにリストされている変数はすべて、サブルーチンが終了するまで自動変数になります。 Newコマンドの2番目の形式には、Cに類似物がありません。 これは、Newコマンドのいわゆる例外的な形式です。 この場合、このコマンドにリストされていない変数はすべて、サブルーチンの実行が終了するまでCの意味で自動的になります。 MUMPSのグローバル変数と自動変数の概念は存在せず、すべてロケールと呼ばれます。 MUMPSのこの状況はいつも私を悩ませてきました。 変数を保護するために各サブルーチンにNewコマンドを含めるのは不便です。 したがって、私はこのデータローカリゼーション方法を放棄することにしました。
MSHには変数のスコープがいくつかあります。
1.サブルーチン呼び出し内でローカライズされた変数、
2.タスク内でローカライズされた変数、
3.アプリケーション内でローカライズされた変数、
4.外部デバイスにある変数。

また、MSHにはMUMPSと同様に変数宣言がないため、スコープを区別するために変数にプレフィックスを付けるには、既知の実績のある古代BASICの唯一の方法を使用する必要がありました。
アプリケーション内でローカライズされた変数には、%%というプレフィックスが付きます。
ジョブ内でローカライズされた変数には、%プレフィックスが付きます。
外部デバイスにある変数には、接頭辞^が付いています。
他のすべての変数は、サブルーチン呼び出し内でローカライズされます。
これにより、素晴らしい新しいチームがなくなりました。

次に、データ構造について説明します。 MUMPSでは、ロケールとグローバルの1つのデータ構造はツリーです。 変数にはインデックスを付けることができますが、インデックスは付けられません。 しかし、グローバルには短縮リンクのようなものがあります。 短縮されたリンクは、プログラムの理解とデバッグの両方を非常に複雑にします。 さらに、短縮リンクがサブルーチンで使用される場合、そのようなサブルーチンを使用してローカル変数を処理することはできません。これは、MUMPS言語の整合性に違反します。 したがって、MSHには短縮リンクはありません。 MUMPS言語の柔軟性が失われないように、間接構文のような非常に疑わしい構造があります。 これにより、最初の変数の名前を含む別の変数を変数の名前として使用できます。 少し不器用に聞こえますが、使用するのと同じくらい不快です。 この言語構​​成体は多くの苦情を提起するため、この構成体はMSHで除外されます。 そして、言語の柔軟性を失わないために、変数名を放棄し、インデックスのみを残すことにしました。 最初のインデックスを変数の名前として扱います。 もちろん、木製のデータ構造は非常に用途が広いです。 ただし、インデックス化されていない単純な変数のアクセス速度は明らかに最適ではありません。 したがって、別のデータ構造がMSHに追加されます-1次元データ配列。

言語コマンドに移りましょう。
引数はコマンドとスペースで区切られます。 MUMPSには、構文的に異なる2種類のコマンドがあります。 最初のタイプのコマンドでは、次のコマンドは前のコマンドとスペースで区切られます。 これらのコマンドでは、スペースは重要であり、余分なスペースは許可されません。 それらが存在すると、構文エラーが発生します。 チームに引数がない場合、チームの後に2つのスペースが続きます。 2番目のタイプのコマンドは、行の終わりで終わります。 そのようなチームが3つあります:For、If、Else。 実際、これらのコマンドは他のコマンドと共にブロックで使用されるため、構文が異なります。 さらに、これらのコマンドは、最初のタイプのコマンドとは異なり、実行の条件がありません。 これらすべてが合わさって、視覚プログラムを書くのは不便であるという事実につながります。
MSHにはわずかに異なる構文戦略があります。
最初に、コマンドの終わりの兆候が導入されます。 スペースは、コマンドと引数の間のセパレーターとして保存されますが、その数は重要ではありません。
次に、ブロック命令の概念が導入されます。 このタイプのコマンドはブロックの始まりであり、ブロックの終わりは終了コマンドです。 コマンド実行条件は、すべてのコマンドに適用されます。 構文はより均一になっています。
ロックコマンド。
MUMPSでは、Lockコマンドは2つの形式で使用されます:ロックおよびロック解除。 MSHでは、ロックコマンドは読み取りロック、書き込みロック、およびロック解除に分かれています。 さらに、タイムアウトのあるロックにはシステムロックが使用されます。 ロックは、主にプロセスを同期し、さまざまなタスクでデータアクセスを同期するために使用されます。 MSHでは、外部デバイスのデータとアプリケーションレベルのデータへのアクセスの同期は言語レベルで実行され、追加のブロックコマンドは必要ありません。
Ifコマンドはブロック状になり、ElseまたはEndで終わるはずです。 このコマンドには引数はありませんが、実行されるコマンドの条件はブロック全体に拡張されます。 ElseコマンドはIfコマンドとともに使用され、実行条件も持つ場合があります。 その後、このチームはElseIfチームになります。 Elseコマンドはブロックであり、ElseコマンドまたはEndコマンドで終了する必要があります。 Elseチームには議論はありません。
もう1つのブロックコマンドは、Forコマンドです。 このコマンドはループを実装します。 コンテンツでは、For MSHコマンドはコマンドのC言語に近いです。 for Cコマンドには3つの引数があります。 最初の引数ループの初期化。 MSHでは、この引数はForコマンドから除外されています。 Setコマンドを使用して、サイクルの前に必要な変数の初期化が実行されます。 Cの2番目の引数は、ループを終了するための条件を設定します。 MSHでは、ループを終了するための条件は、ForおよびEndコマンドを実行するための条件に転送されます。 これにより、Whileおよびdo Whileループコマンドを除外できました。引数のないloopコマンドがこれらのループを実装しているためです。 ループパラメーターを変更するためのCコマンドの3番目の引数は、MSHのForコマンドの引数です。
MUMPSのループに関連する不快な機能が1つあります。 ループ内では、Quitコマンドを使用して完了できます。 しかし問題は、同じコマンドを使用してサブプログラムを完了することであり、ループ内でサブプログラムを完了することは不可能です。 MSHでは、Breakコマンドがループ完了コマンドとして使用され、Returnコマンドがルーチンの完了に使用されます。 終了コマンドは除外されます。
MUMPSでのプログラミングの経験から、90%のケースでForコマンドを使用してツリートラバーサルを整理していることがわかりました。 そして、これは最も便利なチームではありません。 追加のデータ要求が必要です。 したがって、3つのイテレータコマンドとシステムツリートラバーサル機能がMSHに導入されました。
1.次のコマンド-最初から最後までツリーの1レベルをトラバースし、
2. Backコマンド-ツリーの1レベルを最後から最初まで横断し、
3.クエリコマンド-ツリーノードをその深さまで走査します。

MUMPSには、Caseなどの便利なコマンドがありません。 MSHでは、Pascal言語表記で追加されました。Cよりも成功しているように思えました。 さらに、選択変数はどのタイプでもかまいません。 Case MSHコマンドはブロックであり、Endコマンドで終了します。 コマンド内のラベルはブロック内にローカライズされています。

MUMPSには定数のようなものはありませんが、このことは非常に便利です。そのため、ConstコマンドがMSHに追加されました。

継承を整理するために、MSHはExtendコマンドを使用します。
さらに、IncludeコマンドはCから取得されました。これにより、さまざまな部分からプログラムテキストを作成できます。

MSHでは、サブプログラムおよび関数にパラメーターを渡すためのシステムが変更されました。 MUMPSでは、サブルーチンエントリポイントとラベルは、エントリポイントに仮パラメータのリストがある場合があるという点で異なります。 ただし、この場合、パラメーターを渡すことはできませんが、任意のラベル、および場合によってはラベル+オフセットでサブルーチンを呼び出しても干渉しません。 つまり、一般に、エントリポイントからのマークはまったく異なることはありません。 このアプローチはやや論理的でandいものです。 さらに、実際のパラメーターのリストはその数をキャプチャしますが、これは良くありません。 Cでは、松葉杖を使用して、可変数の実際のパラメーターを転送する機能を追加する必要がありました。 MSHでは、私は別のやり方をしました。 MSHには正式なパラメーターのリストはありません。 サブプログラムと関数は、モジュール内のラベルによってアクセスされ、実際のパラメーターは従来の形式で転送されます。 実際のパラメーターは、特別な引数の配列でサブルーチンに入り、その数は配列のゼロ要素に保存されます。

さらに、いくつかの操作が追加されました。その中で最も重要なのは、C構文の選択操作です。

これらはすべて、情報システム用の最新の信頼できる柔軟なプログラミング言語を作成するために行われました。

次に、この言語の正式な説明をします。
MSH言語の説明
内容
1.はじめに
目的。
2.言語の語彙
アルファベット
コメント
3.操作
4.定数
5.変数
6.式
7.チーム
8.機能
9.定義済みのプロパティ。
10.リスト。
11.モジュールの構造。
12.オブジェクト。
13.結論。

1.はじめに
目的
目的:-ソフトウェアのライフサイクルのメンテナンス時間を短縮します。

開発時間の短縮は、次の手段によって達成されます。
-言語は、構文的に単純で簡潔で、可能な限り最小限にする必要があります。
-言語構造は明確で、異常な使用を許可しないようにします。
-言語コマンドのセットは、すべての最新のプログラミングモデルをサポートするのに十分でなければなりません。
-言語は可能な限り柔軟でなければなりません。 変数宣言がないことにより達成されました。

デバッグ時間の短縮は、次の手段によって達成されます。
-プログラムのシンプルさと明快さ。
-プログラムで発生する可能性のある最小限のエラー。
-プログラムには最小限の行が含まれている必要があります。

追跡時間の短縮は、次の手段によって達成されます。
-言語の信頼性。
-言語には、データの整合性を確保する手段が必要です。
-プログラムで発生する可能性のある最小限のエラー。

現代のどの言語も目標に一致しません。 現在、さまざまな言語の大規模な選択があり、それぞれにアイデアが含まれています。 しかし、多くのアイデアはありません。 私は言語で最も価値のあるアイデアを使用しようとします。
最大限の柔軟性を実現するには、言語に特定のプロパティが必要です。特に、宣言的ではありません。 すべての宣言型言語はすぐに柔軟性を失います。 それらのプログラムはすぐに音量が上がります。 翻訳者を支援することに加えて、変数自体の宣言には他の意味はありません。 この言語は、データ操作に焦点を合わせ、ユーザーとの対話を構築するためのツールを含めるべきではありません。 ユーザーとダイアログを構築するためのツールは、特殊な言語のHTMLを提供する必要があります。 言語は、Web開発に向けたものでなければなりません。
意図した目的を最も完全に満たす言語は、プログラミング言語MUMPSです。 私たちはそれを基礎としています。 この言語の最後の標準は1995年の標準であり、出発点になります。

2.言語の語彙

アルファベット
アルファベットは、UTF-8でエンコードされた文字セットです。

コメント
単一行コメント//
複数行コメント/ * * /

言語を記述する場合、オプションのパラメーターは角かっこ内に配置されます<>

3.操作
オペランドには、任意の変数、定数、および関数を使用できます。
単項演算:
'-'単項マイナス負の数の符号。
結果:算術型。
'〜'論理演算はNOT
結果:整数0または1
バイナリ操作:
操作は1〜2文字です。
算術演算:結果の算術タイプ
「+」プラス
「-」マイナス
'*'乗算
「**」べき乗
「/」除算
'\'整数除算結果整数
数値の '#'モジュール結果整数
論理演算:結果整数0または1
「&」演算AND
「|」 操作OR
比較演算:結果整数0または1
'>'詳細
「<」未満
「==」は等しい
'〜='は等しくない
'〜>'もう
「〜<」以上
'> ='以上
「<=」は以下
「<>」は等しくありません
文字列操作:結果の文字列
'_'文字列連結
「_>」行が続く
「_ <」文字列には

ビット単位の文字列操作:
「_&」演算AND
「_ |」 操作OR
'_ ^'排他的OR演算
「_〜」操作はNOT

選択操作:
'?'-C言語標準にほぼ準拠しています。
ExpYcl? ExpTrue:expFalse
expYcl選択条件
expTrue条件が満たされたときに割り当てられる式、
条件が満たされない場合に割り当てられるexpFalse式。

組み込みの操作は、接頭辞「
Arg1 `name Arg2

4.定数
定数は、名前と値で構成されます。 名前は識別子です。 定数値
任意の言語に任意の数の英数字があります。定数値は、引用符または二重引用符で囲むことができます。この場合、任意の文字を引用符で囲むことができます。
定数値の例:123 ABC15'75&56 +”()”““ wq ^er '”
5.変数
言語には変数宣言はありません。変数は、値が割り当てられると発生します。未定義の変数にアクセスすると、空の文字列が返されます。
変数は、ランダムアクセスメモリと外部メモリの両方に存在できます。外部メモリ内の変数には、先頭に^が付きます。
例:^ abc [15、gh8,42] abcはグローバルの名前です。

メモリ内の変数は、スコープとストレージ構造によって分離されます。
1.グローバル。外部デバイスにある変数。これらの変数のプレフィックスは^です。
2.可変タスク。これらは、ジョブ割り当てのすべてのプログラムに共通です。これらの変数には、%
3というプレフィックスが付きます。残りの変数。 Doブロック内でのみ表示されます。
4.擬似配列。 @プレフィックスが付いています。

ストレージ構造は次のようになります
。1.ツリーの構造。このような変数は、角括弧で囲まれた任意のインデックス構造のように見えます。インデックスはコンマで区切られます。インデックスはどのタイプでもかまいません。数値、文字列など。例:ldb [abc、125,5,9]
変数のインデックスは任意の式です。
定義済みの定数thisは名前で使用できます。この場合、オブジェクトのプライベートプロパティを参照しています。このような呼び出しは、メソッド呼び出しまたはオブジェクトプロパティ内でのみ可能です。
例:
[%this] .Age

2.連続配列の構造。
この構造には1つの整数インデックスがあります。配列のすべての要素は行に配置されます。この構造は、データにすばやくアクセスするために使用されます。
配列インデックスは、$記号の後に続きます(
例:$ 25)
配列のインデックスは1から始まります。配列のゼロ要素はサービス要素であり、最後の要素のインデックスが含まれます。イテレータはこの要素を無視します。

3.擬似配列。
サービス情報を送信します。それらへのアピールは、アレイへのアピールに対応しています。
擬似配列のリスト:
prefix @-関数に渡される引数の値、
prefix do @現在のジョブのルーチンスタックの呼び出し、
prefix job @アプリケーションのジョブスタックの呼び出し、
Doブロックのプレフィックスデータ@データブロックスタック、Doブロックの
プレフィックスind @インデックスブロックスタック。

6.式式
は、オペランドと演算の組み合わせです。オペランドは式にすることができ、括弧で囲まれます。変数のタイプは任意です。操作の結果は、操作によって一意に決定されます。操作の優先順位がありません。

7.チーム
異なるチームの議論は異なる場合があります。引数は、=または記号で区切られたサブフィールドで構成できます:
詳細な説明のために、次の規則を受け入れます:exp-表現を
示す接頭辞
expYcl-実行する
ref コマンドの条件を指定する表現-変数参照を示す接頭辞
Prog-.expLabel形式のプログラムへのリンク[expArg <、expArg>]
expMod-値がモジュールの名前である
式expLabel-値がモジュール内のラベルである
式expArg-値が引数である式引数は値で渡されます。

時間間隔は、マイクロ秒10e-6秒で設定されます。

宣言的なコマンド:
Extend、Constant、Include。
宣言コマンドの形式は次のとおりです
。CMDArg <、Arg>;
CMD-コマンドコード。
Argはコマンドの引数です。
宣言コマンドは、プログラムのソースコードに表示されるように、翻訳時に実行されます。それらの実装は、プログラムの進行に依存しません。

拡張コマンド(Ext)。
コマンドの引数は、このモジュールの祖先です。このコマンドは、継承を整理するために使用されます。
expParent <、expParent>を拡張します。
expParent-このモジュールの親の定数名。構文からわかるように、複数の継承が行われます。親選択の優先順位は、継承リストの順序によって決まります。親が早く会うほど、彼の優先順位は高くなります。

チーム定数(定数)。
定数nameConst = valConst <、nameConst = valConst>;
nameConst-定数の名前は識別子であり、その長さは18バイトを超えてはなりません
。valConst-定数の値。英数字または引用符または二重引用符で囲まれた文字で構成されます。

コマンドを含める。
fileName <、fileName>を含めます。
fileNameは、挿入されるファイルの名前です。このコマンドは、リストされたファイルの内容に置き換えられます。

実行コマンド:
Break、Back、Back1、Copy、Do、Else、End、Case、Loop、GoTo、If、Job、KiLL、LockW、LockR、LockUn、Move、Next、Next1、Query、Query1、Return、Set、TimeOut 、トランザクション、EventTrap、EventCall、EventWait、EventDelete、Open、Close、Write、Read。

コマンドの構成:
-コマンドコード-コマンド
を実行するためのオプションの条件
-必須スペース
-コンマで区切られたオプションの引数
コマンドの最後にはセミコロンが付いています。コマンドコードでは大文字と小文字が区別されず、省略される場合があります。完全なコマンドコードは、任意の数のラテン文字または数字で拡張できます。たとえば、EndコマンドはEndIfと書くことができます。同じことが他のチームにも当てはまります。
コマンドを実行するための条件は、コマンドコードからa?実行条件の計算結果が0の場合、コマンドは実行されません。実行条件の計算結果が0でない場合、コマンドが実行されます。
CMD <?ExpYcl> <Arg1 <、ArgN >>;

式セットを評価するコマンド。
セット(S)-形式は次のとおり
ですSet <?ExpYcl> ref = exp <、ref = exp>;
S <?ExpYcl> ref = exp <、ref = exp>;
変数refは式expの値を設定します。

データ削除コマンドを強制終了します。
チームKiLL(K)。
Kill <?ExpYcl> ref <、ref>;
K <?ExpYcl> ref <、ref>;
このコマンドは、refノードの子孫、ノード自体、およびオブジェクトプロパティを削除します。
このコマンドにはまだ変更があります。
refノードのデータを削除します。
KillD <?ExpYcl> ref <、ref>; KD <?ExpYcl> ref <、ref>;
refノードの子を削除します。
KillN <?ExpYcl> ref <、ref>; KN <?ExpYcl> ref <、ref>;
refノードオブジェクトのプロパティを削除します。
KillP <?ExpYcl> ref <、ref>; KP <?ExpYcl> ref <、ref>; 参照ノードオブジェクトのデータとプロパティを削除するなど
、後置記号の組み合わせが可能
です。
KillDP <?ExpYcl> ref <、ref>; KP <?ExpYcl> ref <、ref>;
refノードのデータと子を削除します。
KillDN <?ExpYcl> ref <、ref>; KN <?ExpYcl> ref <、ref>;

データコピーコマンド:
データノードrefFromはノードrefTo
Copy とマージします<?ExpYcl> refTo = refFrom <、refTo = refFrom>;
refFromデータノードはrefToノードに
移動しますMove <?ExpYcl> refTo = refFrom <、refTo = refFrom>;

ジョブロックコマンド
LockW(LW)。
LockW <?ExpYcl> expID <、expID>;
LW <?ExpYcl> expID <、expID>;
expIDで指定された識別子に書き込みロックを設定します。

LockR(LR)。
LockR <?ExpYcl> expID <、expID>;
LR <?ExpYcl> expID <、expID>;
expIDで指定された識別子に読み取りロックを設定します。

LockUn(LU)。
LockUn <?ExpYcl> expID <、expID>;
LU <?ExpYcl> expID <、expID>;
expIDで指定された識別子のロックを解除します。

プログラムの進行を変更するためのコマンド。

TimeOutコマンドは、現在のプログラムの実行を遅らせます。
TimeOut <?ExpYcl> expTime <、expTime>;
expTimeは、現在のプログラムでの計算の遅延を指定する式です。

GOTO(G)コマンドは、プログラム実行の新しいポイントに移動します。
GOTO <?ExpYcl> expMod.expLabel; G <?ExpYcl> expMod.expLabel;
同じモジュールのラベルに移動します。
GOTO <?ExpYcl> expLabel; G <?ExpYcl> expLabel;
expMod-この式を評価した結果はモジュールの名前です。
expLabel-この式を評価した結果は、プログラムの継続ポイントです。

チームを行う
このコマンドは、この実行ブロック内の変数のローカライズでサブルーチン呼び出しを行います。
<?ExpYcl> <expMod。> ExpLabel <[<arg <、arg >>]> <、<expMod。> ExpLabel <[<arg <、arg >>] >>;

ジョブチーム(J)。
チームは新しいタスクでプログラムを実行します。そのような呼び出しごとに、新しいRunブロックとDoブロックが作成されます。
ジョブ<?ExpYcl> ref = <expMod。> ExpLabel <[<arg <、arg >>]> <、ref = <expMod。> ExpLabel <[<arg <、arg >>]>;
ref-ジョブ番号はこの変数に配置されます。

Return(Re)コマンドは、現在のプログラムを終了し、呼び出しプログラムに値を返します。
Return <?ExpYcl> expRet;
Re <?ExpYcl> expRet;
expRet- expressionが評価され、呼び出しプログラムに返されます。

ブロックチーム。
プログラムにはブロックが含まれる場合があります。ブロックはブロック命令で始まり、END命令で終わります。

ブロックコマンドIf(I)。
このコマンドの実行条件がゼロに等しくない場合、Ifコマンドに続くコマンドはElseまたはEndコマンドまで実行されます。 If Endブロック内では、Elseコマンドが発生する場合があります。

実行条件のないElseコマンドは1つのみであり、Elseコマンドチェーンの最後でなければなりません。 Elseコマンドに実行条件があり、この条件がゼロに等しくない場合、ElseまたはEndコマンドが実行されるまでそれに続くコマンド。
これらのコマンドには引数がありません。
If?ExpYcl;私?ExpYcl;
任意のチーム
その他<?ExpYcl;> E <?ExpYcl>; END
コマンド

実行条件のある形式のElseコマンドは実際にはElseIfコマンドであり、実行条件のないElseコマンドです。
一般に、Ifブロックは次のように
なります。
コマンド...
<Else?expYcl;コマンド...>
<その他;コマンド...>
終了;

ブロックチーム選択ケース。
このコマンドは、指定された式に応じてコードのセクションの実行を保証します。このコマンドはPascal表記で使用されます。
式を評価した結果は、文字列になります。
この行がCaseブロック内のラベルの1つと等しい場合、このラベルの後に続くラベルまたはEndコマンドに続くコマンドが実行されます。
文字列がどのラベルとも等しくない場合、<comandElse ...>コマンドが実行されます。

ケース<?ExpYcl> expLabel;
<comandElse ...>
ラベル:comand ...
<ラベル:comand ...>
終了;

ブロックチームトライ。
Tryコマンドは、安全なコードブロックを作成します。プログラム実行時にプログラムで発生するエラーを処理するように設計されています。
試行<?ExpYcl> <Prog [arg <、arg>]>;
コマンド...
終了。
このコマンドの引数は、エラー処理プログラムへのリンクです。この引数は欠落している可能性があります。ブロック内でエラーが発生した場合、処理プログラムが存在するとブロックが終了し、処理プログラムが呼び出されます。

ブロックトランザクション(Tr)コマンド。
Transactionコマンドは、グローバルトランザクションブロックの開始です。このコマンドは、現在のジョブにのみ適用されます。 Jobコマンドがこのブロック内で見つかった場合、現在のトランザクションはJobに拡張されません。ブロックは、1つの引数を持つEndコマンドで終了します。この引数の値が0の場合、トランザクションはロールバックされます。引数が存在しない場合、トランザクションが実行されます。コマンドを実行する条件が偽の場合、ブロック全体は実行されません。
トランザクション<?ExpYcl>;
コマンド...
終了。

ブロックサイクルコマンド。
ループコマンド(L)。
このコマンドには、ループの初期化は含まれていません。ループの初期化は、ループの前に他のコマンドによって実行されます。ループコマンドの実行条件が0になると、サイクルが終了します。 Endコマンドの実行条件が0に等しくない場合、サイクルは終了します。

ループ<?ExpYclFor>;
comand ...
End <?expYclEnd>;

L <?ExpYclFor>;
comand ...
End <?expYclEnd>;

expYclFor-ループを継続する条件。
expYclEnd-ループを終了するための条件。

ブロックループイテレータ。
これらのコマンドは、データを走査するために使用されます。各ステップで、データを持つ次の頂点が使用可能になります。
* Next、Back、およびQueryコマンドの実装ノート。次の注意事項は、Next1、Back1、およびQuery1コマンドには適用されません。
反復子ブロック内では、参照インデックスは変更されません。イテレータブロック内で$ 2または[3]が変更された場合、$$ 2または[[3]]などの式は許可されません。これらの変数の変更は考慮されません。
クロール中、データ構造は変更されません。

チームは、同じレベルのノードの子孫を最初から最後まで(N)トラバースします。
次<?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。
N <?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。

refY-子孫がバイパスされるノードへのリンク。参照インデックス。
RefSaveInd-子サブインデックスが保存されるノードへのリンク。最後の子インデックスのみが保存されます。パラメーターはオプションです。
ノードのプロパティをバイパスする必要がある場合、記号 ':'がインデックスに追加されます。
たとえば、Next [4:]、$ 1

同じレベルでノードの子孫をバイパスの最後から先頭(Ba)にバイパスするコマンド。
戻る<?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。
Ba <?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。

refY-子孫がバイパスされるノードへのリンク。
RefSaveInd-子サブインデックスが保存されるノードへのリンク。最後の子インデックスのみが保存されます。パラメーターはオプションです。

クエリ(Q)ノードのすべての子孫に対する走査コマンド。
Queryコマンドは、ツリーブランチを上から下、左から右に走査します。
クエリ<?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。
Q <?ExpYclEnd> refY <、refSaveInd>;
コマンド...
終了。

refY-子孫がバイパスされるノードへのリンク。
RefSaveInd-子サブインデックスが保存されるノードへのリンク。最後の子インデックスのみが保存されます。パラメーターはオプションです。

ブロックコマンドではありません。

データツリートラバースコマンド。
Next1(N1)コマンドは、同じレベルの次の頂点を提供します。
Next1 <?ExpYclEnd> refY、refSaveInd;

Back1(B1)コマンドは、同じレベルの前の頂点を提供します。
Back1 <?ExpYclEnd> refY、refSaveInd;

refY-子孫がバイパスされるノードへのリンク。
RefSaveInd-子サブインデックスが保存されるノードへのリンク。最後の子インデックスのみが保存されます。パラメーターは必須です。

Query1(Q1)コマンドは、ノード全体を上から下、左から右に走査しながら、ツリーブランチの次の頂点を提供します。
Query1 <?ExpYclEnd> refY、refSaveInd;

refY-子孫がバイパスされるノードへのリンク。
RefSaveInd-子サブインデックスが保存されるノードへのリンク。最後の子インデックスのみが保存されます。パラメーターは必須です。

ループコマンドの終了は、Break(Br)コマンドによってループの任意のポイントで実行できます。
Break <?ExpYclFor>; Br <?ExpYclFor>;

イベント。
このコマンドは、カスタムEventTrap(EvT)イベントの処理を呼び出します。
EventTrap <?ExpYcl> expName <(arg1 <、argN>)> <、expName <(arg1 <、argN>)>
EvT <?ExpYcl> expName <(arg1 <、argN>)> <、expName <(arg1 <、 argN>)>
expNameは、イベントの名前を指定する式です。イベント名は18バイトを超えることはできません。
arg-これらのイベントのハンドラーに渡される引数。
このコマンドの場合、このイベントの開始を待機しているスレッドは継続します。今後、イベント引数は利用可能になります。
このコマンドにより、このイベントのすべてのハンドラーが個別のスレッドで起動され、引数が渡されます。
すべてのイベントハンドラが完了すると、削除されます。
このイベントにハンドラーがない場合、イベントはハンドラーが表示されるまで待機し、その後、処理されて削除されます。

イベント処理コマンド
このコマンドは、EventCall(EvC)イベントハンドラーを割り当てます。
EventCall <?ExpYcl> expName = Prog <、expName = Prog>
EvC <?ExpYcl> expName = Prog <、expName = Prog>
expName-イベントの名前を指定する式。
Prog-イベントハンドラプログラムへのリンク。
このコマンドの実行時にイベントが存在する場合、ハンドラーが呼び出され、イベントが削除されます。

コマンドは、EventWait(EvW)イベントの完了を待機します。
EventWait <?ExpYcl> expName <、expName>
EvW <?ExpYcl> expName <、expName>
イベントの発生を待機し、発生するとタスクが再開します。この瞬間から、EventTrapコマンドによって渡された引数がプログラムで使用可能になります。 EventWaitコマンドの実行時にイベントが存在する場合、実行は継続されます。

EventDelete(EvD)イベントを削除するコマンド。
EventDelete <?ExpYcl> expName <、expName>
EvD <?ExpYcl> expName <、expName>

指定された名前のイベントを削除します。

イベントは、システムで発生するプロセスによってトリガーできます。これらはシステムイベントであり、sysというプレフィックスが付きます。イベントは、プログラムのEventTrapコマンドによってトリガーすることもできます。これらはユーザーイベントであり、先頭にusrが付きます。

システムイベント:
sysJobEnd-ジョブの完了。引数には、完了したジョブの数が渡されます。このイベントは、タスクが完了すると発生します。

外部デバイスと連携するシステムイベント。
これらのイベントは、EventTrapチームによってトリガーされます。ただし、ハンドラーは、イベントが完了したときにのみ呼び出されます。イベントハンドラーが呼び出されると、最初の引数はデバイス識別子を返し、正の整数になります。エラーが発生した場合、この引数にエラーコードが返され、負の整数になります。 2番目の引数(ある場合)は、イベントに依存します。
sysRead-デバイスから読み取ります。デバイスから読み取られたデータは、2番目の引数で渡されます。
ファイル識別子は、引数としてEventTrapコマンドに渡されます。
sysOpenReadClose-これらのイベントのいずれかでイベントが発生します。
ファイル名は、引数としてEventTrapコマンドに渡されます。

ファイルを操作するためのコマンド。
コマンドをファイルに書き込むには:
Write <?ExpYcl> pathFile;
pathFile-文字列値がファイル名である式。
出力値は、事前に引数の配列に配置する必要があります。

ファイルから読み取る:
<?ExpYcl> pathFileコマンドを読み取ります
pathFile-文字列値がファイル名である式。
入力した値は、引数の配列に配置されます。

8.機能。
関数は組み込みおよびカスタムにすることができます。組み込み関数は言語によって定義されます。カスタムはプログラマーによって開発されます。組み込み関数の名前は定数で指定されます。組み込み関数名にはsysプレフィックスが付いています。
実際のパラメーターは、値と名前で関数に渡されます。パラメータが名前で渡される場合、名前にはバック記号が交互に埋め込まれます!..

組み込み関数。
データクロール機能。
%クエリ(refArrInd、<expMod。> ExpLabel)
refArrInd-入力インデックス、
expMod.expLabel-頂点処理関数。
データと追加の頂点インデックスが引数としてこの関数に渡されます。

ロック機能。
%LockR(exp、time)-タイムアウト付きの読み取りロック、
%LockW(exp、time)-タイムアウト付きの書き込みロック、
%LockSt(exp)-ロック状態exp-

値がロック識別子になる式;
結果は18バイトを超えてはなりません。
長さが長い場合、アカウントにのみ最初の18バイト取られる
タイムアウト値-vyrazhenie時間(はusleep)マイクロ秒単位で指定:
戻り値ref =ロック結果
0-現在のジョブをブロックが実行された
<0ロックが達成されていない
0>-№ジョブが予めロックを設定します。ロックに失敗しました。

関数読み取りIniファイルの書き込み
%ReadIni(expFile、refYZL)
%WriteIni(expFile、refYZL)
%WriteIni(OUT、refYZL)
%WriteIni(WWW、refYZL)
関数テキストファイル書き込みの読み取り
%ReadTxt(expFile、refYZL)
%WriteTxt(expFile、refYZL)
%WriteTxt(OUT、refYZL)
%WriteTxt(WWW、refYZL)
ファイル名を指定するexpFile式
refYZL-リンク指定ファイルの行が収まる上部。
標準のオープンデバイス:
OUT-標準出力ストリーム
WWW-ブラウザチャネル

ファイルディレクトリの内容。
%ReadDir(expFile、refYZL)
ディレクトリ名
refYZLを指定するexpFile-expression- ファイルの行が収まる頂点を指定するリンク。

ファイルディレクトリの再帰的なコンテンツ。
%ReadDirR(expFile、refYZL)
ディレクトリ名を指定するexpFile-expression refYZL-
ファイルの行が収まる頂点を指定するリンク。

ファイルディレクトリを作成します。
%CreateDir(expFile)
ディレクトリ名

指定するexpFile式ファイルディレクトリを削除します。
%DeleteDir(expFile)
ディレクトリの名前を指定するexpFile式

削除ファイル。
%DeleteFile(expFile)
ファイル名を指定するexpFile式

関数は、処理されたファイルの数を返します。

ファイルをコンパイルします。
ファイルコンパイル関数:
%Comp(pathFile);
pathFile-文字列値がファイル名である式。
変換の結果、mvm拡張子を持つ仮想MSHマシンのコマンドファイルが作成されます。
戻り値戻りコード= 0または次の形式のエラーメッセージ:
error_code、string、error position。

カスタム関数。
ユーザー定義関数は通常のルーチンであり、Doコマンドの引数の形式を持ちますが、必要な括弧があります。
expMod.expLabel(<expArg <、expArg >>).
expLabel(<expArg <、expArg >>)
expLabel(<expArg <、expArg >>)
expModはモジュールの名前を指定する式です。
ExpLabel-エントリポイント(サブルーチン名)を
指定する式expArg-引数を指定する式。

9.定義済みのプロパティ。
システムプロパティ。
システムプロパティは、システムに関する追加情報を提供します。
%this-オブジェクトインデックス。
%idJob-進行中のジョブのID。
%idDo-ブロックIDを実行します。
%idDivは、現在の入力/出力デバイスです。
%statDo-プログラムの実行ステータス。
%statData-最後のアクセスがあった変数の状態。
%isTrはトランザクションのステータスです。コードがトランザクション内で実行されているかどうか。
%Key-最後のデータアクセスのリンク。
%Data-最後のデータアクセスの値。
%nameMod-実行可能モジュールの名前。

変数のプロパティ。
各変数には事前定義されたプロパティがあります
。%Typeは変数のタイプです
。%Byteは文字列形式のバイト単位の変数のサイズです
。%
size- 文字列形式の文字での変数のサイズ。%stat-変数の状態。
結果のタイプは、プロパティのタイプに従って設定されます。

文字列プロパティ。
これらのプロパティを実行する前に、変数は文字列形式に変換されます。
文字列文字に対するアクション。
StartInd-指定されたアクションを実行する文字のインデックス。
カウント-アクションに関係する文字の数。

1. Get Indインデックスを持つ文字で始まる文字列の文字をカウントします。 Countが設定されていない場合、1と見なされます

たとえば、[j1、j2] = [i1、i2、i3]。%GetStr(startInd <、Count>)。%GetStr(5,3)
2.文字列の文字コードを取得します。インデックスstartInd
。%CodeStr(startInd)
例:[j1、j2] = [i1、i2、i3]。%CodeStr(5)
3
. 行の先頭からCount文字を削除します。%PopStr(Count)
例:[j1、j2] = [i1、i2、i3] 。%PopStr(2)
4. startIndインデックスを持つ文字から文字列に文字を挿入します

例:[i1、i2、i3]。%InsStr(7)= [j1、j2]
または$ 2 = [i1 、i2、i3]。%InsStr(7、[j1、j2])
5
. 文字列のCount文字を置き換えます
たとえば、次のように、。%SetStr(startInd <、Count>):[i1、i2、i3]。%SetStr(4、 3)= [j1、j2]
6.配列から削除します
インデックスstartInd 。%DelStr(startInd <、Count>)を持つ文字から始まる文字をカウントします
例えば:
[j1、j2] = [i1、i2、i3]。%DelStr(5,2)
7. startIndが設定されていない場合、インデックスstartIndの文字から始まる部分文字列を検索し、行の先頭から検索を開始します
。。%FindStr(subStr <、startInd >)
結果:検索された最初の文字の位置。
例えば:
[j1、j2] = [i1、i2、i3]。%FindStr(ABC、2)
8.文字列でcharSource文字をcharRepl文字に置き換えます; charReplが指定されていない場合、文字列からcharSource文字を削除します。。
%ReplStr(charSource <、charRepl> )
例えば:
[j1、j2] = [i1、i2、i3]。%ReplStr(ABC、123)

行のフィールドに対するアクション。
Countが設定されていない場合は、1に等しいと見なします。1
. startIndフィールドで始まる行のフィールドのカウントを取得します。Countが設定されていない場合、Count Count = 1をカウントします

例えば:
[j1、j2] = [i1、i2、i3]。%GetField( '、'、5.3
2.行にフィールドを追加:
。%PushField(delimiter)
for example
[i1、i2、i3]。%PushField( ' 。 ')= [j1、j2]
3. の先頭からCountフィールドを削除します
。Countが設定されていない場合は、Count = 1をカウントします
たとえば、
[j1、j2] = [i1、i2、i3のPopField(区切り文字<、Count>)]。%PopField( 'AB'、2)
4
. 行にフィールドを貼り付けます。%InsField(delimiter、startInd)
例えば:
[i1、i2、i3]。%InsField( '/'、7)= ['-'、j1、j2]
5. startInd
。%SetField(delimiter、startInd <、Count>)で始まるCount行のフィールドを置き換えます
例えば
[I1、I2、I3] SetField%( ' - '、4,3)= [J1、J2]

6 startInd始まる行のカウントフィールドを削除
%DelField(デリミタ、startInd <、カウント>)。
例えば
[j1、j2] = [i1、i2、i3]。%DelField( '-'、5,2)

10.リスト。
任意の変数をリストにすることができます。リストは1つ以上の値で構成されます。値は、リストを含む任意のタイプにすることができます。
作成することでリストを作成できます:
ref = {exp <、exp>}
ref-リストが書き込まれる変数への参照。
expは、対応するリストアイテムになる式です。
リストは、クエリチームから返されることもあります。

参照リンクがリストの場合、インデックス内で対応する数のインデックスに展開されます。
[参照]
各リスト項目は、対応するインデックスになります。リンクでは、通常のインデックスをリストと交互に使用できます。たとえば、変数は次のようになります。
[Af、[B、2]、125、$ 1,5.6]
変数[B、2]および$ 1がリストの場合、リストのサイズに応じてインデックスに展開されます。

リストに対するアクション:
1
. startInd 。%GetList(startInd <、Count>)から始まるリストアイテムのカウントを取得します。
たとえば、[j1、j2] = [i1、i2、i3]。%GetList(5,3)
2.リストに別のリストを追加します

たとえば、
[i1、i2、i3]。%PushList = [j1、j2]
3.リストの先頭から削除します
リストの要素をカウントします。%PopList(Count)
。%PopList-リストの先頭から削除します。 1つの素子
ような
[J1、J2] = [I1 、I2、I3]。%ポップリスト( 2)
4.挿入場所におけるリスト要素は別のリストをstartInd
%InsList(startInd)
例えば
[I1、I2、I3]。 %のInsList (7)= [j1、j2]
5.要素のリストを要素startInd
。%SetList(startInd <、Count>)
開始します(
:[i1、i2、i3]。%SetList(4,3)= [j1、 j2]
6.要素startInd
。%DelList(startInd <、Count>)で始まるCount要素のリストから削除します
たとえば、
[j1、j2] = [i1、i2、i3]。%DelList(5,2)

11.モジュール構造。
モジュールは文字列で構成されています。行はラベルで始まる場合があります。その後、ラベルはコロンになります。ラベルとコロンの間にはスペースを入れないでください。その後、コマンドをスペースバーに続けることができます。コマンドはセミコロン「;」で区切られます。

12.オブジェクト。
モジュールはオブジェクトのタイプ(クラス)として機能できます。モジュール名はオブジェクトのタイプに対応し、18バイトを超えてはなりません。読み取りプロパティの名前は、モジュール内のラベルである必要があります。プロパティは、プロパティ名にプレフィックス「。」が付いたラベルである必要があります。継承は、Extendチームによって提供されます。任意の変数をこのオブジェクトにすることができ、事前定義されたプロパティ.TYPEタイプ名(モジュール)に割り当てるだけです。たとえば、タイプ(モジュール)Orgと、このタイプArgのプロパティがあります。
このタイプのオブジェクトを作成します
。Set [An、12] .TYPE = Org;次に、書き込みおよび読み取りのためのArgプロパティの呼び出しは次のようになります。
[An、12] .Arg = [An、12] .Arg + 1;

13.結論。
記述された言語は目標を達成すると信じています。上記のコマンドセットを使用すると、最新のプログラミング概念をすべて実装できます。タスクを作成し、イベントを処理するためのコマンドが存在するため、プログラミングプロセスを簡素化できます。言語でのデータ管理は、プログラムの開発における多数のエラーを排除します。

著者:シャリモフミハイルアレクシーヴィッチ。電子メール:misha_shar53@mail.ru
この資料を使用する場合は、ソースと著者へのリンクが必要です。

Source: https://habr.com/ru/post/J241369/


All Articles