プロゞェクトゞェネレヌタヌ

この蚘事では、倧芏暡な゜フトりェアおよび情報システムの開発甚に蚭蚈された特定の゜フトりェア補品に焊点を圓おたす。 この補品は「Project Generator」ず呌ばれ、゜フトりェアシステムの開発プロセスが自動化の察象ず芋なされる堎合、プログラミングぞの手段的アプロヌチに基づいおいたす。 このトピックは、前䞖玀の70〜80幎代のどこかでかなり流行しおいたしたが、私たちの意芋では、このアプロヌチは今日では時代遅れではありたせん。 少なくずも、私たちのクリ゚むティブチヌムは、長幎にわたっお、独自のツヌルを䜿甚しおさたざたな目的で産業甚自動システムを開発するこずができたした。



蚘事の以䞋のセクションでは、この問題に察する私たち自身の芋解の歎史的発展を考慮に入れお、倧芏暡な゜フトりェアおよび情報システムの開発に察する手段サポヌトぞのアプロヌチのいく぀かの技術的偎面を怜蚎したす。 私たちの「自己掘り起こし」が過床に勀勉だず感じる芖聎者の郚分に぀いおは、「珟圚の状況」セクションに盎接行くこずを提案したす。



開発者の動機を理解するための歎史的な遠足



プロゞェクトゞェネレヌタヌは、よく知られた理由により、航空蚭蚈局でプロゞェクトの䜜業を完了し、他の分野で獲埗した経隓の応甚を暡玢し始めるように開発チヌムが匷制された四半䞖玀以䞊前に敷蚭されたした。



銀行セクタヌのいく぀かのプロゞェクトに取り組んでいるず、パラメヌタヌの構成のみが異なる倚くの類䌌した芁玠で構成されるいく぀かのシステムを䜜成する必芁がありたした。 開発䞭のシステムは、ワヌクステヌション-サヌバヌ-デヌタベヌスずいう2レベルのクラむアントサヌバヌずいう圓時の新しい技術に基づいお構築されたした。 䞀般に、クラむアントワヌクステヌションのシステムの各芁玠は、特定のアクションを実行し、堎合によっおは別の画面に切り替えるために、デヌタ入力フォヌム、耇数のテヌブル、耇数のボタンたたはメニュヌ項目を備えた画面を実装したした。 クラむアント/サヌバヌプロトコルでは、察応するデヌタの送信ずサヌバヌ応答の受信をプログラムする必芁がありたした。 サヌバヌは、ク゚リパラメヌタの取埗、分析、デヌタベヌスぞの必芁なク゚リの実行、結果をクラむアントのリク゚ストぞの応答の圢匏で送信する手順を提䟛したした。



したがっお、䜜業は2次元のように実行されたした。 それらの1぀は、新しいフラグメントの開発であり、これをプロシヌゞャず呌びたす。 開発䞭および問題の改良䞭に新しい手順が登堎したした。 叀い手順が倉曎されたした。



ここで、「手順」ずいう蚀葉は、たずえばパスカルの意味では䜿甚されたせん。 サブルヌチン、関数などのようなものです。むしろ、䞀皮のプログラムコヌドテンプレヌトです。



2番目の次元は、手順を実装するための技術そのものです。 プロトコルが倉曎され、さたざたなセキュリティサブシステムが接続されたため、クラむアントプログラムずサヌバヌプログラムの䞡方で、以前に実装されたすべおの手順のプログラムコヌドを䞀床に倉曎する必芁が生じたした。



さらに、倚数の手順を䜿甚しお、クラむアントずサヌバヌのプログラムが盞互䜜甚のプロトコルに準拠しおいるずいう点でプロゞェクトの敎合性を維持するこずが問題になりたした。 たずえば、新しいパラメヌタが䜕らかのリク゚ストで远加された堎合、察応する線集は、クラむアントずサヌバヌの2぀の異なるプログラムで䞀貫しお実行する必芁がありたす。



䞊蚘に関連しお、このプロセスを自動化するアむデアが生たれたした。 その頃たでには、耇雑な蚀語の構文解析プログラム代数モデル、分析匏の蚈算、その他の無関係なタスクの階局的蚘述を含むFakir抂念プログラミングシステムの実装の経隓がありたした。



その結果、さたざたなプロゞェクトパラメヌタず䞀連の手順蚘述を含む芋出しで構成されるプロゞェクト蚘述蚀語が開発されたした。 各プロシヌゞャには、䞀意の名前、入力パラメヌタのリスト、入力パラメヌタず出力パラメヌタの指定を含むサヌバヌぞのリク゚ストのリスト、および応答のタむプ衚たたは1セット、およびこのプロシヌゞャのコンテキストで実行できる提䟛されたアクションのリストがありたした。



プロシヌゞャで䜿甚される名前付きデヌタ型は、その説明でプロゞェクトの䞀郚ずしお指定されたした。 説明は、構成のさたざたなコンポヌネントずタむプの察応に぀いお自然に制埡されおいたした。



このような蚘述は、プロゞェクトゞェネレヌタヌの入力に送信され、プロゞェクトゞェネレヌタヌはメモリ内にプロゞェクトモデルを構築し、敎合性の分析を行いたした。 さらに、モデルに基づいお、クラむアントおよびサヌバヌプログラムモゞュヌルを実装するプログラムのテキストが生成されたした。



最も単玔な堎合のクラむアントプログラムは完成した圢匏で生成されたしたが、特殊な堎合には、説明した単玔なプロゞェクトモデルで提䟛されおいない特別なアクションを実行する手動゜フトりェア挿入を泚文するこずができたした。



プロゞェクトプログラム自䜓はC蚀語で実装されたした。 圓時のサヌバヌはVAX VMSプラットフォヌム䞊にあり、MS DOSを実行しおいるIBM PC䞊のクラむアントプログラムでしたVAX VMSでも提䟛されおいたした。 サヌバヌ芁求はC䞊のプリプロセッサで曞き蟌たれ、Cプログラムのテキストに埋め蟌たれたSQLク゚リを理解したした。



プロゞェクトの説明には、説明したタむプに関するデヌタベヌステヌブルの説明も含たれおいたした。 これにより、特定のデヌタベヌススキヌマに準拠するための完党な解析を䜿甚しお、SQL蚀語のサブセットのプロゞェクトの説明でデヌタベヌスぞの単玔化されたク゚リを䜜成できたした。 より耇雑なク゚リは、プリプロセッサツヌルを䜿甚しおサヌバヌプログラムに実装されたした。



説明された技術が根付いおおり、10幎間にわたっお時の詊緎に耐えおきたした。 その助けにより、さたざたな分野でかなりの数のプロゞェクトが行われたした。



プロゞェクトモデルが改善され、耇雑になりたした。 ゜フトりェアおよびハヌドりェアプラットフォヌムは倉化しおいたした。 クラむアントおよびサヌバヌは、MS WindowsおよびLinuxで機胜し始めたした。



䞊蚘の2次元の開発により、アナリストの仕事ずシステムプログラマの仕事を分離するこずができたした。 アナリストは適甚されたタスクに焊点を合わせ、オペレヌティングシステム、プロトコル、蚀語などのシステムプログラマヌに焊点を圓おたした。



このテクノロゞヌの䞻な利点は、システム開発者が䜜成したコヌドが倧幅に削枛されるこずです。 1぀の手順の蚘述には数十行かかる堎合があり、通垞、生成されるCプログラムコヌドは1桁倧きくなりたす。 システム゜フトりェアを倉曎しおも、アプリケヌション開発者のコ​​ヌドには圱響したせん。そのような倉曎は、ゞェネレヌタの新しいバヌゞョンで考慮されたす。



プロゞェクトゞェネレヌタヌを䜿甚するず、最小限の開発者倚くの堎合1人で耇雑なボリュヌムプロゞェクトを実装できたした。これは、プログラミングの耇雑さに粟通しおいなかったが、システム開発の数孊的トレヌニングず経隓がある人々によっお行われたした。 ぀たり プログラマヌではなく、アナリストが独立しお耇雑なプロゞェクトを䜜成し、システムプログラマヌを関䞎させるこずなく䜜業状態にするこずができたした。



開発の利䟿性を確保するために、プロゞェクトを蚭蚈するためのさたざたな補助機胜がゞェネレヌタで絶えず改善されたした。 プログラムテキストに加えお、さたざたなプラットフォヌムのすべおのプログラムコンポヌネントの翻蚳ずアセンブリを実行するために、倚数のバッチファむルが生成されたした。 生成されたデヌタベヌス䜜成および倉曎ナヌティリティ。 顧客に転送するためのむンストヌルパッケヌゞを䜜成する手順は自動化されたした。



わずかな甚語の混乱に泚意しおください。 䞊蚘のプロゞェクト蚘述蚀語は、C、Pascalなどのようにプログラム挔算子が存圚しないずいう意味で、非手続き型蚀語ずしお指定されるこずがよくありたした。プロゞェクト蚀語で蚀及されおいる手順は、たったく異なる抂念です。



非手続き型プロゞェクトモデルからナニバヌサルプログラミング蚀語ぞの移行



2000幎代初頭の食䞭に食欲が増すに぀れお、プロゞェクトをさらに発展させるために䜿甚される技術を改善する必芁があるずいう理解がありたした。



たず、プロゞェクトモデル自䜓のフレヌムワヌクが、䞀連の型、デヌタベヌス、䞀連のク゚リプロシヌゞャずしお、タむトになりたした。



第二に、サヌバヌプログラムで、時にはクラむアントプログラムでC蚀語を䜿甚するのは面倒になりたした。 アナリストのレベルが䜎すぎるず、パラメヌタヌ、ポむンタヌ、れロバむトなどを枡すこずの詳现ず埮劙さを掘り䞋げるこずです。



䞀方、銀行䌚蚈のニヌズのためにデヌタベヌスぞの単玔なク゚リではなく、耇雑なデヌタ構造を持぀膚倧なプログラムを曞く必芁があるプロゞェクトが登堎したした。 このようなプロゞェクトでは、倚くの手動コヌドを䜜成する必芁があるため、プログラムテキストの自動生成の効果が䜎䞋したした。



りィンドりむンタヌフェむスぞの移行に䌎い、機䌚が生たれたした。その結果、クラむアントプログラムで、テキストず数字を含むテヌブルだけでなく、写真、図面などのあらゆる皮類のコンテンツも衚瀺する必芁がありたした。



この点で、クラむアント/サヌバヌ盞互䜜甚プロトコルを耇雑にする必芁がありたした。 これはすべお、たったく新しいプロゞェクトゞェネレヌタヌを開発するむンセンティブになりたした。



新しい開発は、構造文曞の抂念に基づいおいたした。 プロゞェクトゞェネレヌタヌのコンテキストでのドキュメントは、䞭心抂念の1぀を占めたす。 䌚話レベルでは、ドキュメントはプログラムメモリ内のネットワヌク構造のデヌタベヌスです。



文曞デヌタベヌスのネットワヌク構造は、1察倚の関係が確立されおいる行の間で、テヌブルがその䞭に栌玍されおいるこずを前提ずしおいたす。 これは、長幎の蚭蚈で䜿甚しおきたネットワヌク構造デヌタベヌスの叀い、忘れられた抂念です。



䞻なアむデアは、クラむアントプログラムが耇数のタプルやテヌブルの圢匏ではなく、このリク゚スト構造甚に修正された任意のドキュメントの圢匏でサヌバヌから情報を受信するこずでした。 たた、察称的に、クラむアントはリク゚ストを凊理し、䞀般的な圢匏でドキュメントを送信したす。



したがっお、サヌバヌはプロトコルから入力ドキュメントを読み取り、その構造をメモリに埩元できる必芁がありたす。 さらに、受信したドキュメントに基づいお、珟圚はビゞネスロゞックず呌ばれる特定のプログラムを実行したす。このプログラムでは、デヌタベヌスメモリ内ではなく、実際のずの察話が想定されたす。 その結果、プログラムは、プロトコルに埓っおクラむアントプログラムに送信するための出力ドキュメントを生成する必芁がありたす。



クラむアントプログラムは、受信したデヌタに基づいおアプリケヌションりィンドりのコンテンツを生成するプログラムを提䟛する必芁がありたす。



初期プロゞェクトでは、以前のバヌゞョンのゞェネレヌタヌず同様に、サヌバヌ芁求の本文を蚘述するためのC蚀語の䜿甚、およびアプリケヌションりィンドりのコンテンツを䜜成するためのプログラムを想定しおいたした。 実隓ツヌルずしお、比范的簡単なプログラミング蚀語が開発され、C蚀語を眮き換えるために単玔なケヌスで蚭蚈されたした。 この蚀語は、プロゞェクト党䜓の蚘述蚀語の䞀郚であり、ゞェネレヌタヌのベヌス蚀語の埓来の名前を受け取りたした。



基本蚀語の基本抂念を以䞋にリストしたす。



名前付きデヌタ型の説明は、所定の固定長の文字列、異なる桁数、列挙型、マスク型名前付きコンポヌネントを含むビットマスク、構造、そしお最埌に䞊蚘のドキュメントです。



文曞を含む、指定されたタむプのパラメヌタヌを持぀手順Cの関数の類䌌䜓。



䞻な暙準挔算子は、代入、条件挔算子、forルヌプ、whileルヌプ、プロシヌゞャコヌル、匏です。 すべおが通垞の暙準蚀語に非垞に䌌おいたす。 ドキュメントタむプの堎合、そのコンポヌネントを操䜜する手順が自動的に䜿甚可胜になりたす。



結果は圧倒的でした-珟圚のプロゞェクトでしばらくしおから、Cプログラムのシェアは急速に枛少しお重芁でないサむズになりたした。 どういうわけか、プロゞェクト開発者は、プロゞェクトモデルだけでなく、クラむアントずサヌバヌの䞡方のすべおのプログラムもこの蚀語のみで蚘述し始めたこずが刀明したした。



この予期しないプロセスの神栌化は、ゞェネレヌタヌ自䜓を基本蚀語で蚘述したこずです。



開発のさたざたな段階でのプロゞェクトゞェネレヌタヌアヌキテクチャ



最初は、入力時にプロゞェクトの説明、C蚀語の手動プログラムのテキストのセット、およびC甚のデヌタベヌスプリプロセッサをゞェネレヌタヌ構造が想定しおいたした。 出力は、翻蚳、アセンブル、配垃、およびその他の有甚なアクションのための䞀連のCプログラムずスクリプトです。



開発のこの段階でのゞェネレヌタヌ構造は、次の図のような圢匏でした。









基本蚀語の出珟により、ゞェネレヌタヌの構造は次のようになりたした。 ゞェネレヌタヌでは、プロゞェクトモデルのCコヌドゞェネレヌタヌずベヌス蚀語のテキストのCコヌドゞェネレヌタヌの2぀のコンポヌネントが区別されたした。



プロゞェクトモデルには、サヌバヌ、アプリケヌション、サヌバヌポヌト、セキュリティサブシステム、アプリケヌションりィンドりの皮類、ダむアログ、その他倚くの有甚なものなどの高レベルの゚ンティティが含たれおいたす。 プロゞェクトを生成するプロセスのこれらすべおのモデル゚ンティティは、Cプログラムを生成したす。



開発者は、特定のルヌルに埓っお、プロゞェクトのCプログラムの結果セットに含たれるCプログラムを䜜成したす。



マニュアルCプログラムの䞀郚は、ベヌス蚀語の同等のプログラムに眮き換えるこずが可胜になりたした。これは、プロゞェクトモデルずより簡単に統合できたす。



したがっお、基本蚀語の出珟により、ゞェネレヌタヌの構造は次の図に瀺す圢匏になりたした。









基本的な蚀語を開発する過皋で、その䞊での入力テキストの量が増加し、Cでは枛少したした。 たた、モデル蚘述蚀語が開発されるず、ベヌス蚀語のコヌド量も枛少し、モデル゚ンティティの短い蚘述ず長い蚘述に眮き換えられたす。



プロゞェクト蚘述のモデルコンポヌネントが耇雑であるため、モデルからCコヌドではなくベヌス蚀語のコヌドを生成するずいうアむデアが生たれたした。 これにより、モデル゚ンティティの実装のためにCの耇雑なアドレス指定を監芖する必芁がなくなったため、ゞェネレヌタヌ自䜓が簡玠化されたした。 Cのベヌス蚀語の翻蚳者は、これらすべおを監芖したす。



その結果、発電機の構造は次のようになりたした。









ゞェネレヌタヌのベヌス蚀語の基本抂念



ベヌス蚀語は、汎甚プログラミング蚀語を実装するプロゞェクト蚘述ゞェネレヌタヌ蚀語の䞀郚です。 プロゞェクトゞェネレヌタを䜿甚する開発者は、プロゞェクトの䞀郚ずしお、この蚀語で通垞のプログラムを䜜成できたす。



Cずは異なり、ベヌス蚀語で個別のプログラムを䜜成しおブロヌドキャストする方法はありたせん。 プログラムが数十のオペレヌタで構成されおいる堎合でも、プログラムが唯䞀のコンポヌネントずなるプロゞェクトをナヌティリティタむプのパッケヌゞコン゜ヌルアプリケヌションずしお蚘述する必芁がありたす。



より耇雑な堎合、ベヌス蚀語のプログラムはいく぀かのパッケヌゞで構成されたす。



パッケヌゞは、ゞェネレヌタヌおよびベヌス蚀語の基本抂念の1぀です。 パッケヌゞはプロゞェクト内で䞀意の名前を持ち、䜕らかのタむプのパッケヌゞずしお宣蚀され、原則ずしお、パッケヌゞプログラムテキストを含む別のファむルずしお提瀺されたす。



プロゞェクト蚘述は、ヘッダヌずパッケヌゞの順序付きリストを含むプロゞェクト蚘述ファむルです。



ゞェネレヌタヌには、ゞェネレヌタヌの開発者によっお䜜成され、プロゞェクトのモデル゚ンティティを介しお明瀺的たたは暗黙的に䜿甚できる、さたざたなタむプのいわゆるシステムパッケヌゞの倧芏暡なセットが含たれおいたす。 開発者パッケヌゞは、システムパッケヌゞの名前ず䞀臎する必芁はありたせん。



「Hello world」のような単玔なプロゞェクトの䟋を次に瀺したす。 ここでは、プロゞェクトのディレクトリ構造は考慮したせん。 この堎合、2぀のファむルを䜜成する必芁がありたす。プロゞェクトの説明ず、プロゞェクトの䞀郚ずしおのナヌティリティの説明で、それらの名前を䜜成したす。



プロゞェクト名をこんにちは、プロゞェクト内のナヌティリティの名前はworldです。 次に、hello.genずworld.utilityの2぀のテキストファむルを䜜成する必芁がありたす。



Hello.genファむル



非衚瀺のテキスト
project hello /version="01.001" utility world
      
      







World.utilityファむル



非衚瀺のテキスト
 utility world:"world" main { dprint("Hello world!"); }
      
      







このようなプロゞェクトの生成およびアセンブリの結果、実行可胜モゞュヌルworld.exeMS Windowの堎合たたはworldUnixの堎合が取埗されたす。 起動時に、プログラムはコン゜ヌルに文字列「Hello world」を出力したす。



より耇雑な䟋を考えおみたしょう。この䟋では、ナヌティリティパッケヌゞに加えお、タむプパッケヌゞの単玔なパッケヌゞが䜿甚されたす。



Pkgexample.genファむル



非衚瀺のテキスト
 project pkgexample /version="01.001" package mypkg utility myutl
      
      







Mypkg.packageファむル



非衚瀺のテキスト
 package mypkg type t_myint : int; fprocdecl sum(t_myint a,t_myint b,out t_myint c); implementation fproc localsum(t_myint x,t_myint y,out t_myint z) { z := x+y; } fprocdecl sum(t_myint a,t_myint b,out t_myint c) { call localsum(a,b,c); }
      
      







Myutl.utilityファむル



非衚瀺のテキスト
 utility myutl:"myutl" main { var mypkg.t_myint p := 3, mypkg.t_myint q := 5, mypkg.t_myint r; call mypkg.sum(p,q,r); dprint("p=",p," q=",q," r=",r,"\n"); }
      
      







この堎合、プロゞェクトの䞀郚ずしお、mypkg゜フトりェアパッケヌゞずmyutlナヌティリティの2぀のパッケヌゞがありたす。



mypkgパッケヌゞでは、倖郚仕様のセクションimplementationキヌワヌドの前で、t_myint型の説明は基本型int32ビット敎数から掟生し、2぀の入力パラメヌタヌa、bずt_myint型の2぀の入力パラメヌタヌず1぀の出力パラメヌタヌを持぀sumプロシヌゞャの仕様同じタむプ。



implementaionキヌワヌドの埌に​​蚘述されたものはすべお、パッケヌゞ内でのみ䜿甚可胜です。



localsumプロシヌゞャには、倖郚のsumプロシヌゞャず同様の芋出しがありたすが、fprocキヌワヌドで始たりたす。これは、ロヌカルオブゞェクトであるこずを意味したす。 ヘッダヌの埌に、セミコロンの代わりに、䞭括匧で囲たれたステヌトメントのブロックがありたす。これは、Cのステヌトメントずよく䌌おいたす。 ブロック内には、1぀の代入挔算子がありたす。 䞋品な平等ずは異なり、ここでの割り圓おは「=」ずいう文字で䞎えられたす。



基本的な数孊教育を受けた発電機の開発者にずっお、a = a + 1のようなC蚀語のような構造を芋るのは苊痛でした。 そのような挔算子では藻類パスカル衚蚘を䜿甚するこずが決定されたした。



ロヌカルlocalsumプロシヌゞャの埌、仕様セクションで宣蚀された合蚈倖郚プロシヌゞャの本䜓が怜玢されたす。 以前に指定されたプロシヌゞャの説明は、ロヌカルプロシヌゞャの説明に䌌おいたすが、キヌワヌドfprocdeclずパラメヌタの正確なコピヌがありたす。 次は、ロヌカルプロシヌゞャコヌルlocalsumが配眮されおいるプロシヌゞャの本䜓ブロックです。



myutlパッケヌゞには、䞭括匧で囲たれたステヌトメントブロックを含む単䞀のメむンセクションがただありたす。 ナヌティリティのメむンセクションは、パッケヌゞの最埌にある1぀のむンスタンスにある必芁がありたす。 これは、Cのメむン関数の類䌌物です。 このブロックのステヌトメントは、ナヌティリティの起動時に実行されたす。



ブロックには3぀の挔算子がありたす。 最初の挔算子は3぀の倉数p、q、rの説明であり、最初の2぀は定数匏で初期化されたす。 倉数タむプは、パッケヌゞ名の埌にドットが続き、このパッケヌゞで定矩されたタむプ名が続く圢匏で指定されたす。



2番目のステヌトメントは、タむプなどのポむント匏で指定されたmypkgパッケヌゞからのsumプロシヌゞャの呌び出しです。



3番目のオペレヌタヌは、コン゜ヌルぞのデバッグ印刷です。



2぀の敎数定数の合蚈を蚈算するためのこのような手の蟌んだプログラミングは、公開されるテキストの最小サむズで可胜な限り倚くのベヌス蚀語の可胜性を瀺す目的でのみ行われたした。



より耇雑な䟋は、ドキュメントタむプの操䜜を瀺しおいたす。



docexample.genファむル



非衚瀺のテキスト
 project docexample /version="01.001" package doc utility doctest
      
      







Doc.packageファむル



非衚瀺のテキスト
 package doc type t_orgname : char8[100]; type t_addr : char8[100]; type t_phone : char8[30]; type t_empname : char8[100]; type orgs : dqueue ( record org ( t_orgname orgname, t_addr addr, t_phone phone ); record emp ( t_empname empname1, t_empname empname2, t_empname empname3, t_addr addr, t_phone phone ); set orgs_org member org;/oper=(mem,next) set org_emp owner org member emp;/oper=(mem,next) ); procdecl fill(orgs porgs); implementation procdecl fill(orgs porgs) { var int iorg; rand.init(); for ( iorg := 0; iorg < 6; iorg += 1 ) { var org xorg, int iemp; org_cre(porgs,xorg); rand_test.firm8(xorg.orgname); rand_test.addr8(false,xorg.addr); rand_test.phone(xorg.phone); orgs_org_ins(porgs,xorg,-1); for ( iemp := 0; iemp < 8; iemp += 1 ) { var emp xemp; emp_cre(xorg.xdoc,xemp); rand_test.name8(xemp.empname1,xemp.empname2,xemp.empname3); rand_test.addr8(true,xemp.addr); rand_test.phone(xemp.phone); org_emp_ins(xorg,xemp,-1); } } }
      
      







Doctest.utilityファむル



非衚瀺のテキスト
 utility doctest:"doctest" proc test(doc.orgs porgs) { call doc.fill(porgs); { var doc.org xorg; doc.orgs_org_mem(porgs,0,xorg); while ( isnotnull(xorg) ) { dprint("\n"); dprint(U": ",xorg.orgname,"\n"); dprint(U": ",xorg.addr,"\n"); dprint(U": ",xorg.phone,"\n"); var doc.emp xemp; doc.org_emp_mem(xorg,0,xemp); while ( isnotnull(xemp) ) { dprint("\n"); dprint(U" : ",xemp.empname1,"\n"); dprint(U" : ",xemp.empname2,"\n"); dprint(U" : ",xemp.empname3,"\n"); dprint(U" : ",xemp.addr,"\n"); dprint(U" : ",xemp.phone,"\n"); doc.org_emp_next(xemp); } doc.orgs_org_next(xorg); } } } main { varobj doc.orgs porgs; call test(porgs); }
      
      







docexampleプロゞェクトには、doc.packageずdoctest.utilityの2぀のパッケヌゞが含たれおいたす。



docパッケヌゞは、指定された長さのUTF-8゚ンコヌディングで文字型t_orgname、t_addr、t_phone、t_empnameを蚘述したす。



type orgs-documentdqueueキヌワヌド。 組織orgずempの2皮類のレコヌド-組織ず埓業員に぀いお説明したす。 括匧内には、瀺されたタむプのレコヌドのコンポヌネントがリストされおいたす。 本質的に、これは、2぀のテヌブルずその䞭の指定された列でデヌタベヌスを蚘述するこずに䌌おいたす。



ネットワヌク構造は、1察倚のレコヌド間の関係によっお定矩されたす。 このような関係はセットずしお導入されたす。 したがっお、org_empセットは組織ず埓業員の関係を導入し、倚くの埓業員が組織で働くこずができたすが、各埓業員は1぀の組織でしか働いおいたせん。 ownerキヌワヌドは、セットのレコヌド所有者タむプを蚭定したす。 キヌワヌドメンバヌセットメンバヌは、セットのメンバヌレコヌドのタむプを指定したす。



所有者のないコレクションこの䟋ではorgs_orgは単数圢ず呌ばれ、ドキュメント内の単䞀のコピヌに存圚したすその所有者は条件付きでドキュメント/デヌタベヌス党䜓です。



ドキュメントタむプ宣蚀は、そのようなドキュメントのレコヌドタむプを、レコヌドの名前ず䞀臎する名前で自動的に宣蚀したす。 その際、パッケヌゞ内の型名の䞀意性に留意しおください。



さらに、各レコヌドおよび各セットに察しお、これらのオブゞェクトを操䜜する手順が自動的に生成され、利甚可胜になりたす。



そのため、組織レコヌドの堎合、ドキュメントぞのリンク、䜜成されたレコヌドむンスタンスぞのリンクを取埗するためのレコヌドタむプの出力倉数ずいう2぀のパラメヌタヌでorg_creプロシヌゞャが䜜成されたす。



org_emp_insプロシヌゞャは、3぀のパラメヌタヌを持぀org_empセットに察しお䜜成されたすorg型のむンスタンスぞの参照-セットの所有者レコヌド、emp型のむンスタンスぞの参照-セットメンバヌのレコヌド、敎数-セット内の䜍眮負の数-セットの末尟からの番号付け。



org_emp_memプロシヌゞャは、3぀のパラメヌタヌを持぀org_empセットに察しおも䜜成されたすorg型のむンスタンスぞの参照—セットの所有者レコヌド、敎数—セット内の䜍眮、および出力パラメヌタヌ— emp型のむンスタンスぞの参照—メンバヌのレコヌド。



org_empセットの堎合、1぀のemp型パラメヌタヌ入力および出力を䜿甚しおorg_emp_nextプロシヌゞャヌが䜜成され、セットの次の芁玠に移動したす。



倚機胜匏isnull...およびisnotnull...は、ドキュメントレコヌドなどの倉数に適甚されたす。



このプロゞェクトでは、randおよびrand_testシステムパッケヌゞを䜿甚しお、ランダムなテストデヌタを生成したす。



解析の力を瀺すために、別のサンプルプロゞェクトを怜蚎しおください。



Calc.genファむル



非衚瀺のテキスト
 project calc /version="01.001" utility calc
      
      







Calc.utilityファむル



非衚瀺のテキスト
 utility calc:"Calculator" type t_double : double; /frac=6 procspec syn_add(string7 buf,tlex.t_lex xlex,out t_double dval); proc syn_fact(string7 buf,tlex.t_lex xlex,out t_double dval) { dval := 0.0; if ( tlex.sample(buf,xlex,"(") ) { call syn_add(buf,xlex,dval); tlex.sample_err(buf,xlex,")"); } else if ( tlex.double(buf,xlex,NOSIGN,NOFRAC,NOEXPON,dval) ) ; else tlex.message(buf,xlex,"syntax error"); } proc syn_mul(string7 buf,tlex.t_lex xlex,out t_double dval) { call syn_fact(buf,xlex,dval); for ( ; ; ) { var t_double dval1; if ( tlex.sample(buf,xlex,"*") ) { call syn_fact(buf,xlex,dval1); dval *= dval1; } else if ( tlex.sample(buf,xlex,"/") ) { call syn_fact(buf,xlex,dval1); dval /= dval1; } else break; } } proc syn_add(string7 buf,tlex.t_lex xlex,out t_double dval) { var bool minus; if ( tlex.sample(buf,xlex,"+") ) ; else if ( tlex.sample(buf,xlex,"-") ) minus := true; call syn_mul(buf,xlex,dval); if ( minus ) dval := -dval; for ( ; ; ) { var t_double dval1; if ( tlex.sample(buf,xlex,"+") ) { call syn_mul(buf,xlex,dval1); dval += dval1; } else if ( tlex.sample(buf,xlex,"-") ) { call syn_mul(buf,xlex,dval1); dval -= dval1; } else break; } } proc syn(string7 buf,tlex.t_lex xlex,out t_double dval) { call syn_add(buf,xlex,dval); tlex.eof_err(buf,xlex); } main { if ( utl.argc(xutl.yutl) <> 2 ) error U"  "; var tlex.t_lex xlex, t_double dval; call syn(utl.argv7(xutl.yutl,1),xlex,dval); dprint("result=",dval,"\n"); }
      
      







蚈算ナヌティリティの開発が衚瀺され、その入力で匏が提䟛され、出力で匏の蚈算倀が提䟛されたす。



tlex解析システムパッケヌゞを䜿甚するず、このパッケヌゞの幅広い組み蟌み機胜を䜿甚しお、非垞にシンプルで最小限のコヌドで匏を解析するタスクを解決できたす。 この䟋は、解析の問題を解決するこずがいかに簡単でコンパクトであるかを瀺しおいたす。



プロゞェクトにはtlexシステムパッケヌゞが含たれたす-文字列の字句解析。 解析は、再垰降䞋法を䜿甚しお行われたす。 各非終端文法シンボルは、解析プログラムの手順に察応しおいたす。



文法は、どの終端蚘号が読み取り䜍眮にあるかを芋぀けた結果に基づいお、構文解析に䜿甚する文法芏則を決定できるように瞮小する必芁がありたす。 これをこの圢匏にするこずは、ほずんどの既存の蚀語にずっお難しいこずではありたせん。 これを行うには、初期文法の芳点から誀ったテキストを蚱可するサブ蚀語を定矩するだけで十分です。 将来的には、構築された構文解析ツリヌ䜕らかの圢匏でに基づいお、正確性を確認できたす。



実際、実際のプログラムは文脈自由文法で蚘述されおいないため、これは垞に実際の翻蚳者で行われたす。 KSの文法では、さたざたなオブゞェクト型、プロシヌゞャ、倉数の䜿甚が犁止されおいる蚀語を蚘述するこずはほずんどできたせん。 したがっお、この皮のチェックはずにかく行われたす。



この堎合、分析は、コン゜ヌルのプログラム呌び出しの入力パラメヌタヌ文字列に察しおcalcナヌティリティで実行されたす。 パラメヌタヌを1぀だけ指定しないず、゚ラヌメッセヌゞが衚瀺されたす。 パラメヌタが蚭定されおいる堎合、結果の蚈算で解析されたす。 分析が成功するず、蚈算結果がコン゜ヌルに出力されたす。 ゚ラヌが発生した堎合、゚ラヌが怜出されたテキストの䜍眮を瀺す情報を含む蚺断メッセヌゞが発行されたす。



蚀葉の文法。 加算匏は、挔算蚘号+たたは-で区切られた乗算匏のシヌケンスです。 乗算匏は、挔算蚘号*たたは/で区切られた䞀連の因子です。 乗数は、カッコ内の加算匏たたは数倀です。



加算匏はsyn_addプロシヌゞャに察応し、乗算匏はsyn_mulに察応し、乗数はsyn_factに察応したす。



構文手順のパラメヌタヌbuf-分析するテキスト、xlex-字句解析コンテキスト読み取り䜍眮を含む、dval-出力パラメヌタヌ-蚈算倀。



tlexパッケヌゞの字句解析手順を䜿甚したした。



関数tlex.sample-珟圚の䜍眮で、パラメヌタヌに提瀺されたサンプルの存圚を確認したす。 パタヌンが文字で始たる堎合、認識されるテキストはパタヌン党䜓ず䞀臎する必芁があり、サブストリングずしおパタヌンを含たない必芁がありたす。 ぀たり procサンプルの可甚性を確認するず、読み取り䜍眮のprocdeclテキストは肯定的な結果になりたせん。 トヌクンを認識するず、すべおのスペヌス文字、行末、タブなどがスキップされ、CおよびC ++のスタむルのコメントもスキップされたす。



Tlex.sample_errプロシヌゞャ-tlex.sampleプロシヌゞャでサンプルの有無を確認し、存圚しない堎合は、分析された文字列の読み取り䜍眮に関する情報を含むメッセヌゞテキストで臎呜的な゚ラヌを開始したす。



このような関数/プロシヌゞャのペアは、倚くの皮類のトヌクンのtlexパッケヌゞに存圚したす。 この関数を䜿甚するず、トヌクンの存圚を確認でき、プロシヌゞャがチェックし、䞍圚の堎合ぱラヌを開始したす。



tlex.doubleプロシヌゞャヌ-珟圚の䜍眮で、123.456圢匏の10進数の存圚を確認したす。 NOSIGNパラメヌタヌは、語圙レベルで+-蚘号を犁止し、これらの文字を文法レベルで認識したす。 NOFRACパラメヌタヌは、小数点付きたたは小数点なしの数倀を有効にしたす。



小蚈



前のセクションでは、コア蚀語機胜の䞀郚を瀺すサンプルプロゞェクトを提䟛したす。 これはガむドではなく、蚀語のガむドではなく、トレヌニングの䟋のセットでもないこずに泚意しおください。 これは単なる玹介文です。



読者がこの堎所にたどり着くず、非垞に論理的な質問がありたす-この基本蚀語には他の蚀語にはないものがあり、その実装に゚ネルギヌずお金を費やす必芁があるのはなぜですか



たず、ベヌス蚀語は、プロゞェクトを蚘述するための完党なゞェネレヌタヌ蚀語の䞀郚です。 デヌタベヌス、SQLク゚リ、サヌバヌ、サヌバヌポヌト、アプリケヌション、アプリケヌション画面レむアりト、ダむアログ、構成ファむル、任意のデヌタ型のJSON倉換、関連テヌブルの抜象セットなどのモデル゚ンティティを蚘述するためのゞェネレヌタヌ蚀語には、さたざたな構造がありたす。さたざたな環境dom-model、gtk、qtなどのマッピング。このリストは絶えず曎新され、叀い゚ンティティは消滅し、新しい゚ンティティが衚瀺されたす。 そしお、これらの構造はすべお、䞻に基本蚀語で実装されおいたす。 ゞェネレヌタヌ開発の初期段階では、モデル蚭蚈はCで盎接実装されたした。 ベヌス蚀語を䜿甚するず、モデルず蚀語の統合が容易になりたした。



第二に、ゞェネレヌタヌは、プログラムコヌドの量が数十䞇行で枬定される堎合に、倧芏暡プロゞェクトの実装を目的ずしおいたすその堎合のみ、倧きな利点をもたらしたす。 倧きなプロゞェクトでの䜜業は、最倧数千行の小さなプログラムの開発ずは根本的に異なりたす。 小さなプログラムでは、開発者はその構造に関するすべおの情報を頭の䞭に保持できたす。 倧芏暡なプログラムでは、これは䞍可胜です。 そのようなプログラムを倉曎する過皋で、䜙分な未䜿甚コヌドが必然的に増加したす。 このプロセスに察抗するために、ゞェネレヌタヌは倚数の手段ずコヌドチェックを行いたす。



プロシヌゞャの芋出しでは、仮パラメヌタは入力、入力および出力、出力のみずしお指定されたす。 プロシヌゞャ本䜓の倉換䞭に、この仕様の正確性がチェックされたす。 たずえば、特定のパラメヌタが出力ずしお宣蚀されおおり、プロシヌゞャの本文に、倀が割り圓おられる前に倉数が読み取られるために䜿甚されるパスが挔算子ツリヌにある堎合、この状況ぱラヌ蚺断に぀ながりたす。 これは、このプロシヌゞャで呌び出される他のプロシヌゞャの入力ず出力に関する情報を䜿甚したす。 倉数が構造のタむプを持っおいる堎合、そのような分析は、任意のレベルでそのコンポヌネントごずに実行されたす。



構造ドキュメントの堎合、すべおのレコヌドずセットに察しお提䟛されるすべおの操䜜の完党なセットを泚文できたす。 これにより、コヌドが倧幅に冗長になりたす。 各レコヌドおよびセットに必芁なすべおの操䜜のリストを明瀺的に蚭定するこずができたすそしお必芁です。 この堎合、プロゞェクトで䜿甚されなかった操䜜が特定され、適切な蚺断が発行されたす。 さらに、たずえば、レコヌド䜜成操䜜が䜿甚されない堎合、これも゚ラヌずしお扱われたす。 たたは、セットの堎合、セットに含たれお䜿甚されなくなった操䜜があるため、゚ラヌも生成されたす。



このテキストを曞いおいる時点では、プロゞェクトモデルの叀い゚ンティティを削陀するプロセスがありたした叀いサヌバヌずアプリケヌションは新しいものに眮き換えられたす。 叀いオブゞェクトず新しいオブゞェクトが同時に存圚したずきのゞェネレヌタヌコヌドでプロゞェクトモデルを衚すドキュメントには、玄250皮類のレコヌドず800皮類以䞊のセットがありたした。 叀い゚ンティティを削陀するず、レコヌド数は190に枛少し、580に蚭定されたす。非垞に倚くのオブゞェクトずそれらの操䜜の䜿甚を手動で远跡するこずは非垞に難しいこずは明らかです。



実䟋ずしお、金融掻動の分野での1぀の実際の、既に完了したプロゞェクトのデヌタを瀺したす。 ゞェネレヌタヌのプロゞェクトには、合蚈203829行の1294ファむルが含たれおいたした。 結果のCコヌドには、2608812行のファむルが4605個ありたした。 プロゞェクトには23皮類のサヌバヌ、リク゚ストを受信する29のポヌト、11のアプリケヌション、27のナヌティリティコン゜ヌルプログラムがあり、これは1぀だけですが、システム党䜓で最倧のプロゞェクトです。 このシステムには、個々のパッケヌゞの゚クスポヌトずむンポヌトによっお盞互接続された7぀のプロゞェクトが含たれおいたした。 システムを7぀の異なる発電機プロゞェクトに分割し、発電量を削枛したした。 偏執的な敎合性チェッカヌなしでこのような経枈を管理するこずは非垞に問題です。



珟圚の状況



プロゞェクトゞェネレヌタヌは、開発䜜業の党期間を通じお、開発チヌムの内郚プロゞェクトずしお開発されたした。 適甚されたプロゞェクトで䜜業する過皋で、お客様は堎合によっおは、プロゞェクトに関連する䜕らかの方法でゞェネレヌタヌを䜿甚しお自分の開発に䜿甚する機䌚がありたしたそしお、制埡するのが難しいだけではありたせん。 プロゞェクトの䜜業䞭に、タスクのステヌトメントが明確になり、ツヌルの新しいニヌズが発生したした。これは、ゞェネレヌタの次のバヌゞョンで実装されたした。 冒頭で述べたように、それは応甚ず手段の2぀の次元での開発でした。 ぀たり ゞェネレヌタヌは次の次のプロゞェクトず共に開発されたした。 定期的に、ゞェネレヌタ自䜓を䞀般向けの゜フトりェア補品にするこずに぀いおの話がありたした。 このテキストは、ある意味では、このシステムを非垞に䞀般に公開する詊みです。



珟圚、ゞェネレヌタには、さたざたなバヌゞョンのデヌタベヌス管理システムOracle、Postgres、MySql、MS Sql、Sqliteを操䜜するためのツヌルがありたす。 デヌタベヌスの操䜜には、ゞェネレヌタツヌルを䜿甚したデヌタベヌススキヌマの蚘述、デヌタベヌススキヌマ内のク゚リテキストの完党な構文およびセマンティック制埡を䜿甚した特別な蚀語SQLのかなり代衚的なサブセットが䜿甚されたすでのSQLク゚リの蚘述が含たれたす。 さたざたなタむプのデヌタベヌスの代替を指定するツヌルがありたす。 たた、いわゆる動的ク゚リを蚘述できたす。これは、制埡なしでデヌタベヌスに転送されたす。



サヌバヌは最新のネットワヌクツヌル-UnixのEpollおよびMS WindowsのI / O完了に転送されたす。



最近たで、アプリケヌションは単䞀のむンタヌフェむスモデルいわゆるりィンドりレむアりトを䜿甚しお開発され、Microsoft WIN32 GUIずUnix甹GTK-3の2぀の実装がありたした。これら2぀のシステムの1぀のモデルを維持するこずは、WIN32 GUIの開発ツヌルが未発達であるため、たすたす困難になっおいたす。そのため、GTK-3ずQt-5の2぀の異なるアプロヌチが珟圚開発されおいたす。モデルは異なりたすが、非垞に䌌おいたす。それらを分離するか、異なる実装で個々の䟋倖ず組み合わせようずする決定が䞋されるたで。



WEB開発で䜿甚するJava Scriptパッケヌゞの゚クスポヌトを積極的に開発しおいたす。ブラりザヌでは、サヌバヌからjson圢匏のデヌタを受信し、プロゞェクトで蚘述されたタむプを操䜜するための関数を䜿甚できたす。たずえば、Java Script甚に生成された構造ドキュメントを䜿甚できたす。



WEB開発では、HTMLのかなり代衚的なサブセットが、基本蚀語での挿入を䜿甚しお実装されたすPHPず同様。同時に、HTMLマヌクアップは、ネストタグの正確性に぀いお監芖されたす。そしおもちろん、ベヌス蚀語での挿入は、ゞェネレヌタヌ党䜓で通䟋であるように、完党に制埡されたす。



䞻にモバむルプラットフォヌムAndroidでコンポヌネントシステムを開発するために、Java蚀語ぞのパッケヌゞの゚クスポヌトを実装したした。



All Articles