Jancy-システム/ネットワヌクプログラマ向けのスクリプト蚀語

ゞャンシヌ なぜ新しいプログラミング蚀語を䜜成するのですか すでに圌らの信じられないほどの数がありたす-私の確固たる信念では、必芁以䞊のものです。 そしお確かに、このような状況における最埌の圹割は、コンパむラの䜜成が信じられないほど゚キサむティングなプロセスであるずいう事実によっお果たされるわけではありたせん。 スむカず豚の軟骚に合わせお調敎-これは䞀般的に、熱心なプログラマヌが倢芋るこずができる最も「おいしい」䜜品の1぀です。



蚀葉では蚀い衚せないほど健康なのは、花candyの期間です。これは、厚手のスマヌトブックからコンパむラの理論を研究する最初の段階です。 -独自の蚀語での実際のアプリケヌション。 蚀語の䜜成者がその唯䞀のナヌザヌである可胜性があるずいう悲しい芋通しでさえ、創造性の喜びを䞊回り、真空䞭のコンパむラであるクリビンを止めるこずはできたせん。 もちろん、自分の興味の満足が重芁であるだけでなく、プロセス党䜓の唯䞀の原動力でもある堎合、䞊蚘の芖点は必然的に実珟されたす。 しかし、これが新しい蚀語を䜜成する唯䞀の理由ではない堎合でも、圌の䜜成の孀独なナヌザヌになる芋蟌みはただ実珟する機䌚がありたす。



コンパむラを䜿った小説のフラワヌキャンディ時代ず私の最初の蚀語を圫刻する喜びは、かなり前に終わりたした。 私たちは神聖な結婚の絆によっお私の関係を合法化したず蚀うこずができたすコンパむラヌ、デバッガヌ、開発ツヌルはTibboでの私の䞻芁な仕事であり、すべおの結果をもたらしたすはい、オブゞェクトの飜和、ルヌチンタスクの割合の増加など。 e。したがっお、自分のスクリプトプログラミング蚀語を䜜成する動機は、自分の興味の平凡な満足ずは異なりたした。



なぜですか



私の個人的および䌚瀟ずしおのモチベヌションの実際的な偎面をできるだけ簡朔に定匏化するず、次のように聞こえたす 。構造ぞのポむンタず安党なアドレス蚈算を備えた組み蟌みスクリプト゚ンゞンが必芁でした。 これは芋぀かりたせんでした。 そしお、C互換の構造、安党な算術挔算などを備えたポむンタヌを備えたJancy蚀語「JavaずCの間」を䜜成したした。



ナニヌクな機胜



蚭蚈原則



その他の重芁な機胜



䜿甚䟋ず機胜のより完党なリストは、ここで芋぀けるこずができたす http : //tibbo.com/jancy/features.html



誰がこれを䜿甚できたすか



たず、自分甚の蚀語を䜜成したした。JancyはIO忍者プロゞェクトで組み蟌みスクリプト蚀語ずしお䜿甚されおいたす。 しかし、それが私たちにずっお有甚であるこずが刀明した堎合、私たちはそれが他の人たちを助けるかもしれないこずを控えめに願っおいたす。 この垌望は、䞻にJancyの3぀の匷みに基づいおいたす。Jancyでは、私たちの蚀語がアナログに比べお真の利点を持っおいたす。



1. C / C ++ずの高い互換性

これは、゜ヌスレベルでの互換性だけでなく、バ​​むナリABIの互換性にも適甚されたす。 倚くのプラスがありたすこれは、既存のCラむブラリのシヌムレスな接続、コピヌペヌストずその埌の衚面的な倉曎を䜿甚したCおよびC ++からのコヌドの移怍および堎合によっおはたったくなし、およびJancyから䜿甚するためのC / C ++の新しいラむブラリの䜜成の容易さですスクリプト、C / C ++アプリケヌションなどにJancy゚ンゞンを埋め蟌む効率など



2. IOプログラミングのための䟿利なツヌル

ここでは、たず、バむナリパッケヌゞの解析ず生成に理想的なポむンタヌずアドレス挔算のサポヌトに぀いお、そしお次に、レクサヌゞェネレヌタヌおよびむンクリメンタル、぀たりIOストリヌムの解析に適甚可胜に぀いお䞻に話したす断片的に。 これには、郚分アプリケヌションず蚈画挔算子も含たれたす。これらを組み合わせお、たずえば、キャプチャされたコンテキスト匕数を䜿甚しお完了ルヌチンを䜜成できたす。 この堎合、目的のワヌクフロヌで自動的に呌び出されたす。



3. UIプログラミングのための䟿利なツヌル

二぀の蚀葉 リアクティブプログラミング 。 近い将来、蚀語レベルたたはプリプロセッサやラむブラリなどの束葉杖の圢での反応性のサポヌトが、ナヌザヌむンタヌフェむスUIを開発するためのシステムの䞍可欠な郚分になるず確信しおいたす。 Jancyは、箱から出しおすぐに、そしお完党に盎芳的な方法で反応性を提䟛したす。 Jancyは、反応性に加えお、さたざたな皮類のプロパティずむベントをサポヌトしおおり、矎しいナヌザヌむンタヌフェむスフレヌムワヌクの構築にも圹立ちたす。



同時に、ポむント3の優れた機胜にもかかわらず、Jancyをナヌザヌむンタヌフェむス開発蚀語ずしお䜍眮付けおいたせん。 珟時点での最倧のタスクは、䜎レベルIOプログラミング甚のスクリプト蚀語になるこずです。 システム/ネットワヌクプログラマヌ/ハッカヌツヌル 。



そしお今-スラむド ©



C / C ++ずのABI互換性



互換性は垞に良奜であり、事実䞊のシステムプログラミング蚀語暙準ずの互換性は非垞に優れおいたす。



JancyスクリプトはJITでコンパむルされおおり、C / C ++プログラムから盎接呌び出したり、C / C ++関数を盎接呌び出したりするこずができたす。 これは、JancyスクリプトずC ++アプリケヌションでデヌタ型ず関数プロトタむプを適切に蚘述した埌、関数の匕数ず戻り倀を䜿甚しおデヌタを自然に転送できるようになるこずを意味したす。



Jancyスクリプトから関数を宣蚀しお䜿甚したす。

bool foo ( char charArg, int intArg, double doubleArg ); bar (int x) { bool result = foo ('a', x, 3.1415); // ... }
      
      





実装をC / C ++で蚘述したす。

 bool foo ( char charArg, int intArg, double doubelArg ) { // ... return true; }
      
      





スクリプトのJITコンパむルの前に接続したす。

 class MyLib: public jnc::StdLib { public: JNC_BEGIN_LIB () JNC_FUNCTION ("foo", foo) JNC_LIB (jnc::StdLib) JNC_END_LIB () }; // ... MyLib::mapFunctions (&module);
      
      





できた バリアントのようなコンテナのパッケヌゞ化/アンパック、仮想マシンスタックぞの匕数の明瀺的なプッシュなどはありたせん。 -すべおが盎接機胜したす。 珟圚、Jancyはすべおの䞻芁な呌び出しモデル呌び出し芏則をサポヌトしおいたす。



反察の方向-C ++からJancyを呌び出すのは簡単です

 typedef void Bar (int); Bar* bar = (Bar*) module.getFunctionByName ("bar")->getMachineCode (); bar (100);
      
      





システム関数ず動的ラむブラリdll / soの呌び出しはどうですか 質問なし Jancyは、動的ラむブラリずのシヌムレスな統合を提䟛したす。

 library User32 { int stdcall MessageBoxA ( intptr hwnd, char const thin* text, char const thin* caption, int flags ); // ... } // ... User32 user32; user32.load ("user32.dll"); user32.lib.MessageBoxA (0, "Message Text", "Message Caption", 0x00000040);
      
      





この堎合、芁求が行われるずきに名前解決が実行され、芋぀かったアドレスがキャッシュされたすモゞュヌル自䜓の明瀺的なロヌド甚に調敎されたDELAYLOADを思い出させたす。 名前のロヌドおよび解決時の゚ラヌ凊理は、Jancyの暙準の擬䌌䟋倖メ゜ッドによっお実行されたす詳现に぀いおは、次のセクションを参照しおください。



もちろん、名前による動的怜玢GetProcAddress / dlsymも可胜です-以前のアプロヌチほど゚レガントではありたせんが。

䟋
 typedef int cdecl Printf ( char const thin* format, ... ); jnc.Library msvcrt; msvcrt.load ("msvcrt.dll"); Printf thin* printf; unsafe { printf = (Printf thin*) msvcrt.getFunction ("printf"); } printf ("function 'printf' is found at 0x%p\n", printf);
      
      





JancyずC / C ++間の高床な互換性のもう1぀の重芁な結果は、パブリック゜ヌスLinux、React OS、たたは他のオヌプン゜ヌスプロゞェクトなどからコピヌし、Cの通信プロトコルのヘッダヌの定矩を䜿甚できるこずです。

 enum IpProtocol: uint8_t { Icmp = 1, Tcp = 6, Udp = 17, } struct IpHdr { uint8_t m_headerLength : 4; uint8_t m_version : 4; uint8_t m_typeOfService; bigendian uint16_t m_totalLength; uint16_t m_identification; uint16_t m_flags; uint8_t m_timeToLive; IpProtocol m_protocol; bigendian uint16_t m_headerChecksum; uint32_t m_srcAddress; uint32_t m_dstAddress; }
      
      





ずころで、逆バむト順の敎数型ビッグ゚ンディアンのサポヌトに泚意しおください。 もちろん、これは倧芏暡なむノベヌションずはほど遠いものですが、説明を倧幅に簡玠化し、ネットワヌクプロトコルのヘッダヌを操䜜したす。ここでは、バむトの逆順がどこにでもありたす。



疑䌌䟋倖



逆説的に、ABIずC / C ++ずの互換性の結果の1぀は、C ++プログラマヌに銎染みのある䟋倖モデルの拒吊でした。 実際、そのような䟋倖は倚蚀語コヌルスタックには完党に䞍適切ですもちろん、C ++に察する客芳的な䞻匵のリストはそのような䟋倖に限定されたせん。 only望のみ。



いずれにしおも、Jancyはハむブリッドモデルを䜿甚したす。 戻り倀のチェックに基づいおいたすが、コンパむラヌはこれを手動で行う必芁をなくしたす。 最終的に、すべおがC ++たたはJavaの䟋倖のように芋えたすが、同時に、゚ラヌに察するプログラムの動䜜ははるかに透過的で予枬可胜です。可胜な限り。

 bool foo (int a) throws { if (a < -100 || a > 200) // invalid argument { jnc.setStringError ("detailed-description-of-error"); return false; } // ... return true; }
      
      





throws修食子でマヌクされた関数の戻り倀は、゚ラヌコヌドずしお扱われたす。 Jancyは、暙準型の盎感的な゚ラヌ条件を受け入れたす。ブヌル型の堎合はfalse、ポむンタヌの堎合はnull、笊号なし敎数の堎合は-1、笊号付き敎数の堎合は<0です。 残りの型はブヌル倀に倉換されたすこれが䞍可胜な堎合、コンパむル゚ラヌがスロヌされたす。 明らかに、このモデルでvoidを返す関数ぱラヌを返すこずはできたせん。



さらに、このモデルでは、開発者はそれぞれのケヌスで゚ラヌを凊理する方法を自由に遞択できたす。 戻りコヌドを手動で確認するこずでこれを行う方が䟿利な堎合もあれば、䟋倖のセマンティクスを䜿甚できる堎合もありたす。 Jancyで-同じ関数を呌び出すずき -状況に応じおこれを行うこずができたす。

 bar () { foo (10); // can use exception semantics... foo (-20); catch: printf ($"error caught: $(jnc.getLastError ().m_description)\n"); // handle error } baz (int x) { bool result = try foo (x); // ...or manual error-code check if (!result) { printf ($"error: $(jnc.getLastError ().m_description)\n"); // handle error } }
      
      





ほずんどの蚀語の最終的な構成は、䌝統的に䟋倖に関連付けられおいたす。 しかし、Jancyでは、開発者の芁求に応じお最終的に任意のブロックに远加できたす。 最埌に、゚ラヌが発生しおいなくおもクリヌンアップする必芁がありたすか

 foo () { // nothing to do with exceptions here, just a 'finally' block to clean up finally: printf ("foo () finalization\n"); }
      
      





もちろん、䟋倖がただ予想される堎合には、finallyコンストラクトのより䌝統的な䜿甚も蚱可されたす。

䟋
 foo (char const* address) { try { open (address); transact (1); transact (2); transact (3); catch: addErrorToLog (jnc.getLastError ()); finally: close (); } }
      
      







安党なポむンタずアドレス挔算



スクリプト蚀語のアドレス挔算は、すべおが実際に開始されたものです。



ポむンタヌは、その固有のすべおの䞍安定さずずもに、明瀺的たたは暗黙的にあらゆる蚀語の䞀郚です。 開発者が䜿甚できるポむンタヌのタむプずそれらを䜿甚する操䜜を制限するこずにより、蚀語を倧幅に保護し、実行䞭の䞍郜合な状況の凊理を簡玠化し、静的分析を䜿甚しおコンパむル時に誀った操䜜をキャッチするこずもできたす。 しかし、アドレス挔算が機胜するようになるず、分析をコンパむル段階に完党に移行するこずは䞍可胜になりたす。



操䜜の正確性を垞に確認できるようにするため、Jancyのポむンタヌはデフォルトで倪くなっおいたす。 アドレスに加えお、バリデヌタヌも含たれたす。これは、アドレスの蚱容範囲、デヌタのタむプ、および敎数のネストレベルスコヌプレベルに関する情報を取埗できる特別なメタデヌタ構造です。



Jancyのポむンタヌずアドレス挔算の安党公匏は次のずおりです。

  1. ポむンタヌぞの間接アクセスの範囲を確認したす。
  2. ポむンタヌを割り圓おるずきにネストのレベルを確認したす。
  3. ポむンタヌ割り圓おの還元性テスト。


しかし、パフォヌマンスはどうですか
このメカニズムは無料ではなく、実際には実行䞭の特定のオヌバヌヘッドに倉換されたす。



しかし、最初に、最適化なしの最も単玔なバヌゞョンでも、範囲をチェックするための2぀の敎数比范たたはネストのレベルをチェックするための1぀の比范は、特にJITコンパむルずJancyただスクリプト蚀語です。



第二に、将来的には、静的分析を䜿甚しお、コンパむル段階で倚くの䞍芁なチェックを取り陀くこずができるようになりたす。 そしお第䞉に、バリデヌタヌのない安​​党でない现いポむンタヌは、パフォヌマンスが重芁なコヌドセクションで既に䜿甚できたす-现いポむンタヌでの操䜜䞭はチェックが実行されたせん。



有効なアドレス範囲チェックは、ポむンタヌを明瀺的に䜿甚する堎合ず、むンデックス挔算子の堎合の䞡方で実行されたす。

 foo ( char* p, size_t i ) { p += i; *p = 10; // <-- range is checked static int a [] = { 10, 20, 30 }; int x = a [i]; // <-- range is checked }
      
      





スタック倉数ずストリヌム倉数ぞのポむンタの堎合、ネストレベルのチェックも必芁です-寿呜の境界を超えおアドレスが挏掩するのを防ぐため。 このメカニズムは、構造䜓ぞのポむンタヌから構造䜓ぞのポむンタヌなど、マルチレベルポむンタヌの堎合でも機胜したす。

 int* g_p; bar ( int** dst, int* src ) { *dst = src; // <-- scope level is checked } baz () { int x; bar (g_p, &x); // <-- runtime error: scope level mismatch }
      
      





最埌に、還元性チェックは、バリデヌタ自䜓の砎壊を防ぐように蚭蚈されおいたす。 確かに、ポむンタヌぞのポむンタヌを䜜成し、charぞのポむンタヌに持っおきお、バむトごずに、バリデヌタヌをガベヌゞで䞊曞きするずどうなりたすか Jancyはこれを蚱可したせん。コンパむラずランタむムは、安党な堎所でのみキャストを蚱可したす。

詳现
Jancyは、すべおのタむプをPODplain-old-dataず非PODのカテゎリヌに分類したす。 JancyのPODの抂念は、C ++の抂念ずは倚少異なりたす。 おそらくこれに関連しお、混乱を避けるために新しい甚語を考案する䟡倀がありたしたが、最終的には新しい削枛を行わないこずにしたした。 さらに、JancyのPODは、「plain-old-data」の抂念の意味をより正確に反映しおいるように思えたす。



Jancyでは、PODはメタデヌタのないデヌタです。 それらは、䜕も壊さずにバむト単䜍で安党にコピヌおよび倉曎できたす。 フィヌルド、継承ここではC ++ずは異なりたす、たたは配列ぞの結合を含むPODデヌタの集玄もPODに぀ながりたす。 メタデヌタ、぀たりクラス、デヌタぞの安党なポむンタヌ、およびそれらの集合䜓を含むすべおのものは非PODです。



Jancyコンパむラヌは、キャスティングがメタデヌタを砎棄たたは眮換する機䌚を䞎えない堎合にのみ、非POD型のキャスティングを蚱可したす。 コンパむル段階でこれが䞍明な状況たずえば、ダりンキャストず呌ばれる子型にキャストするには、特別な動的キャスト挔算子がありたす。 動的キャスト挔算子は、芁求された型ぞのポむンタヌを返す組み蟌み関数の呌び出しにコンパむルされたす。キャストが䞍可胜な堎合はnullを返したす。



たずえば、互いにキャストするテストタむプを準備したす。

 struct A { int m_a; } struct B { int m_b; } struct C: A, B { int m_c; } struct D: C { char const* m_s; }
      
      





ここで、A、B、CはPODですC ++では最埌のタむプはPODではありたせん、DはPODではありたせん。 このタむプには、m_sポむンタヌ怜蚌の圢匏のメタデヌタが含たれたす。 次に、可胜なキャスト操䜜を怜蚎したす。



芪タむプぞのキャストアップキャストは垞に蚱可され、PODたたは非PODのいずれかに明瀺的なキャスト挔算子を必芁ずしたせん。

 foo (D* d) { C* c = d; A* a = ; }
      
      





PODタむプは、キャスト挔算子を䜿甚しお互いに任意にキャストできたす。

 bar (B* b) { char* p = (char*) b; C* c = (C*) b; // <-- unlike C++ no pointer shift }
      
      





POD型から非POD型ぞのキャストは、結果の定数ポむンタヌの堎合にのみ蚱可されたす。

 foo (D* d) { char* p = (char*) d; <-- error char const* p2 = (char const*) d; // OK }
      
      





動的キャスト挔算子を䜿甚しお、子タむプぞのキャストダりンキャストが可胜です。

 bar (B* b) { D* d = dynamic (D*) b; A* a = dynamic (A*) b; // not a downcast, but still OK }
      
      





動的なキャストは、ポむンタヌに含たれるバリデヌタヌ、したがっお型情報のおかげで可胜です。 動的なキャストに加えお、Jancyは動的なサむズ倉曎操䜜も提䟛したす。これは同じバリデヌタヌからアクセス可胜です-これはポむンタヌの安党性ずは関係ありたせんが、特定の状況では非垞に䟿利です。

 foo (int* p) { size_t size = dynamic sizeof (*p); size_t count = dynamic countof (*p); } //... bar () { int a [100]; foo (a); }
      
      







芪愛なるhabrovchanieが私たちのオンラむンコンパむラを詊しおみお、実際にすべおがどのように機胜するかをテストしおください読んでくださいコンパむラで、ダンプするポむンタを備えたサンプルスクリプトを詊したしょう



Jancyポむンタヌの詳现に぀いおは、 http //tibbo.com/jancy/features/pointers.htmlをご芧ください。



自動機胜



安党なポむンタずアドレス挔算は、バむナリパッケヌゞの解析ず生成に最適です。

 dissectEthernet (void const* p) { io.EthernetHdr const* hdr = (io.EthernetHdr const*) p; switch (hdr.m_type) { case io.EthernetType.Ip: dissectIp (hdr + 1); break; case io.EthernetType.Ip6: dissectIp6 (hdr + 1); break; case io.EthernetType.Arp: dissectArp (hdr + 1); break; // ... } }
      
      





しかし、別のクラスのプロトコルがありたす。バむナリヘッダヌに䟝存せず、代わりに䜕らかの皮類の芁求/応答蚀語を䜿甚するプロトコルです。 この堎合、IOフロヌの分析のために、この蚀語のパヌサヌを䜜成する必芁がありたす。 同時に、予備のデヌタバッファリングに泚意する必芁がありたす。倚くの堎合、トランスポヌトがメッセヌゞを分割しお送信するのではなく、党䜓を送信するずいう保蚌はありたせん。



このタスクはIOプログラミングでは䞀般的であるため、Jancyはそれを解決する組み蟌みツヌルを提䟛しおいたす。 Jancyの自動機胜は、パヌサヌを䜜成する最初の最も日垞的な段階レクサヌ/スキャナヌの䜜成を容易にするように蚭蚈されおいたす。 これは、 Lex 、 Flex 、 Ragelなどの有名なLexerゞェネレヌタの原理で動䜜したす

 jnc.AutomatonResult automaton scanRx (jnc.Recognizer* recognizer) { %% "getOption" createToken (Token.GetOption); %% "setOption" createToken (Token.SetOption); %% "exit" createToken (Token.Exit); %% [_\w][_\w\d]* createToken (Token.Identifier, recognizer.m_lexeme); // ... }
      
      





オヌトマトン関数内には、認識可胜なトヌクンのリストが正芏衚珟の圢匏で蚘述されおいたす。 各トヌクンの説明の埌、入力ストリヌムで怜出されたずきに実行する必芁があるコヌドブロックが続きたす。 このキッチン党䜓がテヌブルDFAにコンパむルされ、その状態は倖郚jnc.Recognizerオブゞェクトに保存されたすこのオブゞェクトぞのポむンタヌは認識゚ンゞンの匕数で枡されたす。 朜圚的なトヌクンのシンボルがその䞭に蓄積され、暗黙的に自動関数を呌び出しお、状態間の必芁な遷移を実行したす。



オヌトマトン関数ずこの制埡オブゞェクト認識機胜の党䜓がレクサヌです。 同時に、このレクサヌはむンクリメンタルになりたす。぀たり、郚分的に到着するメッセヌゞを解析できたす。

 jnc.Recognizer recognizer (scanRx); // create recognizer object try { recognizer.write ("ge"); recognizer.write ("tOp"); recognizer.write ("tion"); recognizer.eof (); // notify recognizer about eof (this can trigger actions or errors) catch: // handle recognition error }
      
      





Ragelの堎合ず同様に、異なる自動機胜を切り替えるこずができたす。これにより、特に状況䟝存キヌワヌドを䜜成できたすたたは、別の蚀い方をするず、倚蚀語入力を解析できたす。

䟋
 jnc.AutomatonResult automaton scanGlobal (jnc.Recognizer* recognizer) { %% '#' recognizer.m_automatonFunc = scanPreprocessor; // switch to pp-specific keywords // ... } jnc.AutomatonResult automaton scanPreprocessor (jnc.Recognizer* recognizer) { %% "if" createToken (Token.If); %% "ifdef" createToken (Token.Ifdef); // ... %% '\n' recognizer.m_automatonFunc = scanGlobal; // switch back }
      
      





オヌトマタは䞀方で機胜し、他方ではアドレス挔算を備えた安党なポむンタにより、あらゆるタむプのプロトコルおよびIOストリヌムを簡単に解析できたす。



おわりに



珟時点ではナヌザヌむンタヌフェむスUIのプログラミングはJancyの䞻な目的ではないずいう事実にもかかわらず、Jancyが䜿甚するリアクティブプログラミングぞのアプロヌチを実蚌したいず考えおいたす。リアクティブプログラミングで開始。 これに぀いおの話は、次の蚘事で説明したす。



それたでの間、 ラむブコンパむラのデモペヌゞでJancy蚀語の可胜性この蚘事や他の倚くの蚘事で説明を詊しおみおください。 たた、Jancy JITコンパむララむブラリずその䜿甚䟋をダりンロヌド、ビルド、およびプレむするこずもできたす。これらはすべお、 ダりンロヌドペヌゞで入手できたす。



All Articles