JS-Interpreterの勉強メモ

JS-Interpreterとは、JavaScriptで記述するサンドボックス化されたJavaScriptインタープリターです。Javascriptコードを実行する時には、任意のJavaScriptコードを１行ずつ実行に行きます。JavaScript環境から完全に分離されています。JS-Interpreterのインスタンスが複数に作られた場合は、Web稼働環境(ブラウザーなんとか)を使用せずに複数のJavaScriptコード同時にマルチスレッドで実行することが可能です。

#環境準備
以下の2つのJavaScriptソースファイルをインポートします。

    <script src="acorn.js"></script> 
    <script src="interpreter.js"></script>
  
または、圧縮バンドルを使用します。

    <script src = "acorn_interpreter.js"> </ script>
  
#使い方１：外部API無し
外部APIが使わない場合は、JS-Interpreterの初期化関数を使用せずに、インスタンスを作ります。
Javascriptコードをステップごとに実行するには、step関数をfalseを返すまでに繰り返し呼び出します。
コードがが無限ループではなく安全なコードだって言うことが分かれば、run関数を1回のみ呼び出してコードを最後までに実行することが構わないです。

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
	var runButton = document.getElementById('runButton');
	var stepButton = document.getElementById('stepButton');
	var myInterpreter = null;
	var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;};';
    myInterpreter = new Interpreter(myCode);
	function stepCode() {
		if(this.myInterpreter.step()){
			window.setTimeout(stepCode,0);
	   	}
	}
	function runCode() {
		myInterpreter.run();
	}
</script>
</body>
</html>
```

#使い方2：外部APIあり（標準Javascriptコードの場合）
外部APIが使った場合は、JS-Interpreterの初期化関数を利用してインスタンスを作ります。
ただし、例えば、外部APIがalertようなJavascriptの標準コードであれば、JS-Interpreterの初期化関数を作成する時には、Javascriptのコードを定義することが必要だけです

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
	var runButton = document.getElementById('runButton');
	var stepButton = document.getElementById('stepButton');
	var myInterpreter = null;
	var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;alert(i);};';
	//初期化関数
	var initFunc = function(interpreter, scope) {
		var wrapper = function(text) {
        	return alert(text);
      	};
      	interpreter.setProperty(scope, 'alert', interpreter.createNativeFunction(wrapper));		
    };
    myInterpreter = new Interpreter(myCode, initFunc);
	function stepCode() {
		if(this.myInterpreter.step()){
			window.setTimeout(stepCode,0);
	   	}
	}
	function runCode() {
		myInterpreter.run();
	}
</script>
</body>
</html>
```

#使い方2：外部APIあり（関数が自分定義した場合）
外部APIがJavascriptの標準コードではなく、自分で定義した関数を実行する場合には、JS-Interpreterの初期化関数を作成する時に、自分の関数を定義することが必要で、さらに、この関数の処理の詳細も記述する関数も定義しないと行けません

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
	var runButton = document.getElementById('runButton');
	var stepButton = document.getElementById('stepButton');
	var myInterpreter = null;

	var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;console_log(i);};';

	var initFunc = function(interpreter, scope) {
		var wrapper = function(text) {
        	return console_log(text);
      	};
      	interpreter.setProperty(scope, 'console_log', interpreter.createNativeFunction(wrapper));
    };
    myInterpreter = new Interpreter(myCode, initFunc);
	function stepCode() {
		if(this.myInterpreter.step()){
			window.setTimeout(stepCode,0);
	   	}
	}
	function runCode() {
		myInterpreter.run();
	}
	function console_log(value){
		console.log(value.data);
	}
</script>
</body>
</html>
```
実行結果は下記です。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229009/1c71b7a0-2bc5-37a9-6dca-1cce6389aed3.png)