パート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.sln 、 stack_usageプロジェクトを開きます。