34行のJavaScriptスタックプログラミング言語



スタック言語とは何かを知らない人のための情報:


次の行はウィキペディアから非常にコピーされています

スタックプログラミング言語は、スタックのマシンモデルを使用してパラメーターを渡すプログラミング言語です。



言語について


言語は非常にシンプルになります。たとえば、関数は1つのパラメーターしか取得できませんが、それでもサンプルと比較する可能性があります。 タイプは1つのみ、つまり数値です。



マッチング関数は次のように定義されます:

value name = operations





valueが一致するパターンである場合、operationsは関数の本体です。



関数が一致せずに定義されている場合、次のように記述されます。

name = operations





ただし、関数の本体では、関数が呼び出されたオペランド、つまりスタックの最上部になる値を持つ定数opを使用できます。



スタックに値を入力するには、数値を入力するだけです。



そして、スタックの最上位要素を変数に変換するには、次のように記述する必要があります。

-> name





標準操作のうち、+-* /のみが



したがって、たとえば、スタックの先頭から要素を1増やす関数は、次のように記述されます。

++ = op 1 +







ただし、階乗関数を実装するには、サンプルとコードとの比較が必要になります。

0 ! = 1

! = op 1 - ! op *












実装


コンテキストとして実装されるインタプリタのみが記述されます。

別のスクリプトがこのコンテキストで機能します。 詳細は説明しません。 私はそれがスタックの一番上または「コンソール」の「nil」を表示すると言うことができます



最初のステップ


まず、予想どおり、コンテキストをコンストラクターとして記述し、HContextを示します。



HContext = function(){

this.stack = []; //

this.vars = []; //

this.funs = []; //



}








次に、引数がコードになる最も重要な関数「run」を作成し、関数自体がそれをトークンに分割し、これが関数の定義であることが判明した場合、目的の関数を呼び出します。そうでない場合は、コード実行関数を呼び出します。



this.run = function(code){

lexems = code.split(' ');

if(lexems.oneOf('=')){

this.define(lexems);}else{

this.exec(lexems,'');}}







注:コードを注意深く読んだ人はoneOfメソッドに気付くことができます。これは、「extend.js」と呼ばれるメソッドですこのライブラリのその他の機能も適用されます。



次に、コードを実行するexec関数を作成します。 最初に、op引数が定義されていない場合、値3を割り当てます。



次に、トークンの配列をステップスルーし、トークンに応じてさまざまな操作を実行するループを作成します。

'op'の場合、値opをスタックに入れます。

この番号の場合-スタックに置きます。

その名前の変数がある場合、その値をスタックに入れます。

その名前の関数がある場合、それを呼び出します。 呼び出し機能

数学的操作のいずれか-それを呼び出します。 Mathop関数

そして、それが->-の場合、カウンターを1増やし、スタックの最上部からの現在のトークン値を名前とする変数を割り当てます。



this.exec = function(code,op){

op = op || 0;

for(var cp=0;cp<code.length;cp++){

if(code[cp]=='op'){this.stack.push(op)}

else if(code[cp].isNum()){this.stack.push(parseFloat(code[cp]))}

else if(this.vars[code[cp]] != undefined){this.stack.push(this.vars[code[cp]])}

else if(this.funs[code[cp]] != undefined){this.call(code[cp])}

else if(this.mathOps.oneOf(code[cp])){this.mathOp(code[cp])}

else if(code[cp] == '->'){cp++;this.vars[code[cp]]=this.stack.pop();}}}//









数学演算




可能な数学演算を使用して配列を作成しましょう。

this.mathOps = ['+','-','*','/'];







それでは、関数を定義しましょう。 スタックから上位2つの値を取得し、操作の結果をスタックの先頭に配置します。



this.mathOp = function(op){

nums = [this.stack.pop(),this.stack.pop()];

this.stack.push(eval(nums[1] + ' ' + op + ' ' + nums[0]));}








機能


さて、すでに述べたように、関数について話しましょう、比較が行われますが、関数を格納する単純なモデルのため、その実装は非常に簡単になります。

関数はfunsリストに保存され、各関数は 'op'キーを持つ要素が一致しない関数になり、他のすべてが一致するリストになり、キーが一致するテンプレートになります。



関数定義メソッドを書きます:



this.define = function(code){

eq = code.pos('='); //

op = code[eq-2] || 'op'; // 2 = 'op'

name = code[eq-1]; // 1

cmds = code.slice(eq+1); // 1

if(this.funs[name] == undefined){this.funs[name] = [];} // ,

this.funs[name][op] = cmds; // }








そして、関数を呼び出します。このために、呼び出しメソッドを選択します(ほとんどの、特にアセンブラーのプログラマーは、間違いなく面白い名前を見つけられません)



this.call = function(fun){

op = this.stack.pop(); //

cd = this.funs[fun][op] || this.funs[fun]['op']; //

this.exec(cd,op);} //








試すには:


疑似コンソールはこちらです。 例もあります。



All Articles