ObjectScript API、C ++との統合。 パート1:スタックの操作、C ++からのOS関数の呼び出し

ObjectScriptは、新しいオープンソースのオブジェクト指向プログラミング言語です。 ObjectScriptは、JavaScript、Lua、PHPなどの言語の機能を拡張します。 彼のプレゼンテーションは、 この記事でしばらく前にハブで行われ、読者の間で興味と熱烈な議論を呼び起こしました。 そのため、プレゼンテーションにこだわらず、ObjectScript APIについて説明しないことにしました。 APIの説明をいくつかの部分に分けて、記事をできるだけ短くするようにします。



パート1:スタックの操作、C ++からのOS関数の呼び出し



OS(ObjectScript)を使用した最小限のプログラムは次のとおりです。



#include "objectscript.h" using namespace ObjectScript; int main() { OS * os = OS::create(); // TODO: main code here os->release(); return 0; }
      
      





つまり OSインスタンスを作成し、それを使用して正しくdelete



ます。ただし、 delete



オペレーターだけでなく、 release



メソッドを呼び出します。



OSインスタンスは必要な数だけ同時に作成でき、必要に応じて、互いに完全に独立して動作します。



次に、 TODOの代わりに配置する必要があるコードの例を示しますメインコードはこちらです。



それでは、C ++を使用して次のOSコードをシミュレートしましょう。



 print("10 * (3+2) = ", 10 * (3+2))
      
      





ここにあるもの:2つのパラメーターを持つグローバル関数の呼び出し。1つ目は定数文字列、2つ目は数学演算の結果です。



最初に行うことは、関数呼び出しを準備することです。 これを行うには、スタックに2つの値を配置する必要があります。1つ目は関数自体で、2つ目はこの関数の値です。 たとえば、静的関数など、関数がこれを使用しない場合、 null



this



として配置する必要があります。 このようにします:



  os->getGlobal("print"); // #1 -     os->pushNull(); // #2
      
      





次に、関数が呼び出されるパラメーターをスタックに追加します。



  os->pushString("10 * (3+2) = "); // #3 -  
      
      





次に、2番目のパラメーターの数学演算をシミュレートします。



  os->pushNumber(10); // #4 os->pushNumber(3); // #5 os->pushNumber(2); // #6 os->runOp(OP_ADD); // #5 - 3+2 os->runOp(OP_MUL); // #4 - 10 * (3+2)
      
      





できた! runOp



メソッドは、OSカーネルを使用して、スタック内の値に対して数学、論理、およびビットごとの演算子を実行できます。 つまり、必要に応じて、型変換などが行われます。... OP_ADD



は、スタックの最上部の2つの値(つまり、最後に2回スタックに置かれた値)に対して加算演算子を実行します。 この場合、結果はスタック上の値を置き換えます(つまり、2つの値がスタックから削除され、結果が追加されます)。 OP_MUL



乗算についても同様です。



現時点では、スタックに4つの値があります: 1-関数、 2 -null、 3-文字列、 4-数値。 いいね! あなたは電話することができます:



  os->call(2); //    2 
      
      





それだけです、私たちはコンソールを見ます(コンソールに印刷結果を印刷)、それは次のようになります:



 10 * (3+2) = 50
      
      





この場合、スタックは完全に空になります。 関数を呼び出すときに使用される4つの値は、スタックから削除されます。



例2



OSで次のコードをシミュレートします。



 bar = {firsname="James", lastname="Bond"} bar.profession = "actor" print bar
      
      





スタック上に新しいオブジェクトを作成します。



 os->newObject(); // #1
      
      





最初のプロパティfirsname="James"



設定します。



 os->pushStackValue(-1); // #2
      
      





-1は、スタックの最上部への相対ポインターです。 プロパティを設定するスタックにオブジェクトを追加します(オブジェクトは参照によりスタックに追加されます)。



 os->pushString("firsname"); // #3 -   os->pushString("James"); // #4 -    os->setProperty(); // #1
      
      





setProperty



メソッドは、プロパティを設定し、使用されている値をスタックから削除します(この場合、スタックの最上部で3つの値が使用されます:オブジェクト、プロパティ名、および値)。



2番目のプロパティでも同じことを行いますが、より短い方法で行います。



 os->pushString("Bond"); // #2 -  os->setProperty(-2, "lastname"); // #1
      
      





-2はスタックの先頭から2番目の値への相対ポインターであり(これがオブジェクトです)、文字列"Bond"



がスタックの先頭になりました。



オブジェクトをグローバル変数barに保存します



 os->setGlobal("bar"); // #0
      
      





現在、スタックには値がありません。 次に、コードbar.profession = "actor"



実行します。



 os->getGlobal("bar"); // #1 -      bar os->pushString("actor"); // #2 os->setProperty(-2, "profession"); // #1 os->pop(); // #0 -    bar  
      
      





完了、 print bar







 os->getGlobal("print"); // #1 os->pushNull(); // #2 os->getGlobal("bar"); // #3 os->call(1); // #0
      
      





コンソールを見ると、次のようになっているはずです。



 {"firsname":"James","lastname":"Bond","profession":"actor"}
      
      





例3



OSで次のコードをシミュレートします。



 print(concat(5, " big differences"))
      
      





通常どおり開始します。



 os->getGlobal("print"); // #1 -      print os->pushNull(); // #2 -  this   print os->getGlobal("concat"); // #3 -      concat os->pushNull(); // #4 -  this   concat os->pushNumber(5); // #5 -    concat os->pushString(" big differences"); // #6 -    concat os->call(2, 1); // #3 -   concat
      
      





この段階で、2つのパラメーターを使用して関数を呼び出し、出力で1つの結果を要求しました(0の結果を要求した場合、concatは1つのデフォルト結果を返します。関数呼び出しの後、2つ以上の値が必要な場合、最初の結果はconcat関数からのもので、残りはnullで補完されます)。



次にprint



呼び出しprint







 os->call(1); // #0
      
      





コンソールでは次のようになります。



 5 big differences
      
      





プログラムの全文:



 #include "objectscript.h" using namespace ObjectScript; int main() { OS * os = OS::create(); /* print("10 * (3+2) = ", 10 * (3+2)) */ os->getGlobal("print"); // #1 - stack values, it's print function from standart library os->pushNull(); // #2 - null, it's function this, each call of function must have this // push the first argument os->pushString("10 * (3+2) = "); // #3 - we have 3 stack values here // prepare second argument os->pushNumber(10); // #4 os->pushNumber(3); // #5 os->pushNumber(2); // #6 os->runOp(OP_ADD); // #5 - 3+2 os->runOp(OP_MUL); // #4 - 10 * (3+2) os->call(2); // call function with 2 arguments /* bar = {firsname="James", lastname="Bond"} bar.profession = "actor" print bar */ os->newObject(); // #1 - new object os->pushStackValue(-1); // #2 - the same object, -1 - is relative pointer to the top stack value os->pushString("firsname"); // #3 - property key os->pushString("James"); // #4 - property value os->setProperty(); // #1 - setProperty uses 3 stack values and pop them // second way of same functionality os->pushString("Bond"); // #2 - property value os->setProperty(-2, "lastname"); // #1 os->setGlobal("bar"); // #0 - assign object value to global bar variable, pop value // let's do bar.profession = "actor" os->getGlobal("bar"); // #1 - our global a variable os->pushString("actor"); // #2 - property value os->setProperty(-2, "profession"); // #1 os->pop(); // #0 // let's do print bar os->getGlobal("print"); // #1 os->pushNull(); // #2 os->getGlobal("bar"); // #3 os->call(1); // #0 /* print(concat(5, " big differences")) */ os->getGlobal("print"); // #1 - print function os->pushNull(); // #2 - this for print os->getGlobal("concat"); // #3 - concat function os->pushNull(); // #4 - this for concat os->pushNumber(5); // #5 os->pushString(" big differences"); // #6 os->call(2, 1); // #3 - result is already at the top of stack os->call(1); // #0 os->release(); return 0; }
      
      





ObjectScriptのソースコードとサンプルは、 このリンクのこの記事からダウンロードでき、 proj.win32 \ examples.slnstack_usageプロジェクトを開きます。



All Articles