OSDN Git Service

ELCCIDE(elcc/elccide.html)を追加。ブラウザ上でソースコードを編集し、即座に実行することができます。
authorhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 25 Jan 2014 08:00:14 +0000 (17:00 +0900)
committerhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 25 Jan 2014 08:00:14 +0000 (17:00 +0900)
コンパイラの独立性を高めました。elcc/header.jsでincludeしているソースのみで動作します。

ai.js
aiext.js
elcc/elcc.js
elcc/elccide.html [new file with mode: 0755]
elcc/header.js [new file with mode: 0644]
webcpu/api.js
webcpu/instrbas.js
webcpu/readme.txt
webcpu/webcpu.js

diff --git a/ai.js b/ai.js
index 77e84e9..5cb6d73 100644 (file)
--- a/ai.js
+++ b/ai.js
@@ -248,8 +248,11 @@ AI.prototype = {
        inputProcess_CompileELCHNOS_OSECPU: function(str, srctype){
                this.debug("**** Start Processing (CompileELCHNOS_OSECPU) ****\n");
                
-               var cc = new ELCHNOSCompiler(this);
-               cc.compile(str);
+               var that = this;
+               var cc = new ELCHNOSCompiler(function(s){ that.debug(s); }, this.downloadBox);
+               if(cc.compile(str) == null){
+                       cc.saveBinary();
+               }
                
                this.debug("**** End Processing (CompileELCHNOS_OSECPU) ****\n");
        },
index 8709489..16e4c3d 100644 (file)
--- a/aiext.js
+++ b/aiext.js
@@ -181,13 +181,17 @@ Array.prototype.propertiesNamed = function(pName){
        }
        return retArray;
 }
-Array.prototype.logAsHexByte = function(){
+Array.prototype.logAsHexByte = function(logfunc){
        //十六進バイト列としてデバッグ出力する。
+       //logfuncは省略時はconsole.logとなる。
+       if(logfunc === undefined){
+               logfunc = function(s){ console.log(s); };
+       }
        var ds = "";
        for(var i = 0, iLen = this.length; i < iLen; i++){
                ds += ("00" + this[i].toString(16).toUpperCase()).slice(-2);
        }
-       console.log(ds);
+       logfunc(ds);
 }
 Array.prototype.stringAsHexByte = function(){
        //十六進バイト列として文字列を得る
index 57f9e62..a5c00e6 100644 (file)
@@ -1,4 +1,5 @@
 // ELCHNOSCompiler for AI004
+// AI004(WebCPU)がなければ動作しない。
 
 //手順:
 //トークン分割
@@ -31,7 +32,7 @@ ELCHNOSCompiler_CompileException.prototype = {
                        s += ":" + this.errorMessageList[this.errno] + "\n";
                }
                if(this.infoArray){
-                       s += "  >" + this.infoArray.toString() + "\n";
+                       s += "  >" + this.infoArray.join("\n  > ") + "\n";
                }
                return s;
        },
@@ -39,17 +40,16 @@ ELCHNOSCompiler_CompileException.prototype = {
 // throw new ELCHNOSCompiler_CompileException(5, [""], this.lineCount);
 
 
-function ELCHNOSCompiler(env){
-       this.env = env;
-       
-       this.line = null;
-       this.separated = null;
-       this.bin = new Array();
-       
-       this.structure = new Array();
-       this.currentStructure = this.structure;
-       this.structureStack = new Array();
+function ELCHNOSCompiler(printFunc, downloadBoxDOMObject){
+       //printFunc省略時はconsole.logに出力。
+       if(printFunc){
+               this.debug = printFunc;
+       } else{
+               this.debug = function(s){ console.log(s); };
+       }
+       this.downloadBoxDOMObject = downloadBoxDOMObject;
        
+       this.reset();
        //0はエントリポイント(main)用に予約
        this.nextLabelID = 1;
        this.integerRegisterAllocationTable = new Array();
@@ -99,8 +99,24 @@ ELCHNOSCompiler.prototype = {
        
        Flag_Sign_Signed                        : 0x00000001,
        Flag_Sign_Unsigned                      : 0x00000002,
-       
+       reset: function(){
+               this.line = null;
+               this.separated = null;
+               this.bin = new Array();
+               
+               this.structure = new Array();
+               this.currentStructure = this.structure;
+               this.structureStack = new Array();
+               
+               //0はエントリポイント(main)用に予約
+               this.nextLabelID = 1;
+               this.integerRegisterAllocationTable = new Array();
+               this.pointerRegisterAllocationTable = new Array();
+       },
        compile: function(str){
+               //戻り値nullでコンパイル成功
+               this.reset();
+               //
                this.line = str.split("\n");
                //分割
                this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
@@ -479,20 +495,27 @@ ELCHNOSCompiler.prototype = {
                        }
                        this.expandBinaryString();
                        this.assignRegister();
-                       this.bin.logAsHexByte();
+                       this.bin.logAsHexByte(this.debug);
+                       this.debug("\n");
+                       //
+                       
+                       //
                        var cpu = new WebCPU();
                        cpu.loadBinaryText(this.bin.stringAsHexByte());
                        cpu.staticOptimize();
-                       console.log(cpu.createBackendBinaryString());
-                       this.saveBinary();
+                       this.debug(cpu.createBackendBinaryString());
+                       this.debug("\n");
+                       //
                } catch(e){
                        //全エラー処理
                        if(e instanceof ELCHNOSCompiler_CompileException){
-                               this.env.debug(e.getMessageString());
+                               this.debug(e.getMessageString());
+                               return e;
                        } else{
                                throw e;
                        }
                }
+               return null;
        },
        compile_removeComment: function(){
                //コメント削除
@@ -540,7 +563,7 @@ ELCHNOSCompiler.prototype = {
                                        iLen -= len - linesInCommentBlock;
                                        linesInCommentBlock = 0;
                                } else if(commentBlockCount < 0){
-                                       this.env.debug("Too many block comment closure [].\n");
+                                       this.debug("Too many block comment closure [].\n");
                                        return;
                                }
                        } else if(commentBlockCount > 0 && s == "\n"){
@@ -550,12 +573,12 @@ ELCHNOSCompiler.prototype = {
        },
        raiseError: function(errno, lineCount, infoArray){
                if(errno < 0 || this.errorMessageList.length <= errno){
-                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
+                       this.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
                } else{
-                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
+                       this.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
                }
                if(infoArray){
-                       this.env.debug("  >" + infoArray.toString() + "\n");
+                       this.debug("  >" + infoArray.toString() + "\n");
                }
        },
        changeCurrentStructure: function(newstructure){
@@ -730,12 +753,25 @@ ELCHNOSCompiler.prototype = {
                }
        },
        saveBinary: function(){
-               var m = this.env.IOManager;
                var cl = this.bin;
                var v = new Uint8Array(this.bin);
                var d = new Blob([v]);
+               var url;
                if(d){
-                       m.showDownloadLink(d);
+                       if(window.URL){
+                               url = window.URL.createObjectURL(d);
+                       } else if(window.webkitURL){
+                               url = window.webkitURL.createObjectURL(d);
+                       } else{
+                               window.alert("Can't create URL");
+                       }
+                       if(url){
+                               if(this.downloadBoxDOMObject){
+                                       this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>ダウンロード</a>";
+                               } else{
+                                       this.debug("BinarySaved: " + url + "\n");
+                               }
+                       }
                }
        },
        
diff --git a/elcc/elccide.html b/elcc/elccide.html
new file mode 100755 (executable)
index 0000000..c206b20
--- /dev/null
@@ -0,0 +1,203 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9">
+<meta charset="UTF-8">
+<title>ELCC-IDE</title>
+<style type="text/css">
+       h1, h2, h3 {
+               margin:0px;
+       }
+       body, textarea {
+               font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
+               font-size: 14px;
+               line-height: 1.2;
+       }
+       #fileDropZone {
+               border: 2px dashed #bbb;
+               padding: 25px;
+               text-align: center;
+               font: 20pt bold;
+               color: #bbb;
+       }
+</style>
+<script type="text/javascript" src="./header.js" charset="UTF-8"></script>
+<script type="text/javascript">
+
+var mainCPU = null;
+var mainCompiler = null;
+var codeTextArea = null;
+var debugMessageTextArea = null;
+var maxDebugMessageLength = 0x1000;
+var binStr = null;
+
+onload = function(){
+       debugMessageTextArea = document.getElementById('debugMessageText');
+       mainCPU = new WebCPU();
+       mainCompiler = new ELCHNOSCompiler(messageOut);
+
+       mainCPU.setMainWindowCanvasDOMObject("mainWindowCanvas");
+       enableDebugMode();
+       
+       // Setup the dnd listeners.
+       var dropZone = document.getElementById('fileDropZone');
+       dropZone.addEventListener('dragover', handleDragOver, false);
+       dropZone.addEventListener('drop', handleFileSelect, false);
+       
+       //Enable Tab key in textarea
+       codeTextArea = document.getElementById('codeText');
+       //http://d.hatena.ne.jp/hokaccha/20111028/1319814792
+       codeTextArea.addEventListener("keydown", function(e) {
+               if (e.keyCode === 9) {
+                       e.preventDefault();
+                       var elem = e.target;
+                       var val = elem.value;
+                       var pos = elem.selectionStart;
+                       elem.value = val.substr(0, pos) + '\t' + val.substr(pos, val.length);
+                       elem.setSelectionRange(pos + 1, pos + 1);
+               }
+       });
+       
+}
+
+function messageOut(s){
+       var str = debugMessageTextArea.value + s;
+       if(str.length > maxDebugMessageLength){
+               str = str.slice(str.length - (maxDebugMessageLength >> 1));
+       }
+       debugMessageTextArea.value = str;
+       debugMessageTextArea.scrollTop = debugMessageTextArea.scrollHeight;
+}
+
+function compile(){
+       debugMessageTextArea.value += "****Compile Started****\n";
+       if(mainCompiler.compile(codeTextArea.value) == null){
+               messageOut("*\n****Compile Succeeded!****\n*\n");
+               binStr = mainCompiler.bin.stringAsHexByte()
+       } else{
+               messageOut("*\n****Compile Failed...****\n*\n");
+               binStr = null;
+       }
+}
+
+function run(){
+       if(binStr){
+               mainCPU.loadBinaryText(binStr);
+               mainCPU.execute();
+       }
+}
+
+function enableDebugMode(){
+       mainCPU.setDebugMessageDOMObject("debugMessageText");
+       mainCPU.message("****Debug mode enabled.\n");
+}
+
+function disableDebugMode(){
+       mainCPU.message("****Debug mode disabled.\n");
+       mainCPU.setDebugMessageDOMObject(null);
+}
+
+// http://www.html5rocks.com/ja/tutorials/file/dndfiles/
+function handleFileSelect(evt){
+       evt.stopPropagation();
+       evt.preventDefault();
+
+       var files = evt.dataTransfer.files; // FileList object.
+       
+       // files is a FileList of File objects. List some properties.
+       var output = [];
+       for(var i = 0, f; f = files[i]; i++){
+               output.push('<li><strong>', escape(f.name), '</strong> ', f.size, ' bytes, last modified: ', f.lastModifiedDate.toLocaleDateString(), '</li>');
+               var r = new FileReader();
+               r.onload = (function(file){
+                       return function(e){
+                               var a = r.result;
+                               codeTextArea.value = a;
+                       }
+               })(f);
+               r.readAsArrayBuffer(f);
+       }
+}
+
+function handleDragOver(evt){
+       evt.stopPropagation();
+       evt.preventDefault();
+       evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
+}
+</script>
+</head>
+<body>
+<h1>ELCC-IDE</h1>
+<div style="float:left;">
+       <h2>mainWindow</h2>
+       <canvas id="mainWindowCanvas" width="640" height="480" style="border:1px solid #000000;"></canvas>
+       <h2>Internal Information</h2>
+       <input type="checkbox" onchange="">message</input><br />
+       <textarea id="debugMessageText" cols="66" rows="16"></textarea>
+       <form onsubmit="return false;">
+               <button onclick="compile();">Compile</button>
+               <button onclick="run();">Run</button>
+               <button onclick="mainCPU.stopFlag = true;">Break</button><br />
+               <button onclick="enableDebugMode();">EnableDebugMode</button>
+               <button onclick="disableDebugMode();">DisableDebugMode</button>
+       </form>
+</div>
+<div style="float:left;">
+       <h2>Code</h2>
+       <textarea id="codeText" cols="80" rows="48" wrap="off">
+unsigned char table[32] = {
+       196, 100, 187,  61, 164,  29, 129,   9,
+        90,   5,  53,  17,  23,  44,   7,  81,
+         7, 119,  23, 156,  53, 183,  90, 195,
+       129, 191, 164, 171, 187, 139, 196, 100,
+};
+
+procedure inline drawLine(int mode, x0, y0, x1, y1, col){
+       @asm OSECPU
+       REMARK 05 0100000003;
+       R30 = 0xff45;
+       R31 = mode;
+       R32 = x0;
+       R33 = y0;
+       R34 = x1;
+       R35 = y1;
+       R36 = col;
+       CALL P28;
+       REMARK 01 00;
+       @end
+}
+
+procedure main()
+{
+       int x0, y0, x1, y1, col, i, j;
+       unsigned char *p, *q;
+
+       p = table;
+       for (i = 0; i != 15; i++) {
+               x0 = *p;
+               p++;
+               y0 = *p;
+               p++;
+               
+               q = table;
+               for (j = -8; j != 8; j++) {
+                       x1 = *q;
+                       q++;
+                       y1 = *q;
+                       q++;
+                       col = i - j;
+                       if (col <= 0){
+                               col = 1 - col;
+                       }
+                       if (col <= 7) {
+                               drawLine(1 + 4, x0, y0, x1, y1, col);
+                       }
+               }
+       }
+}
+       </textarea>
+       <div id="fileDropZone">Drop SourceCode.elc here</div>
+       <div id="fileList"></div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/elcc/header.js b/elcc/header.js
new file mode 100644 (file)
index 0000000..32f07bf
--- /dev/null
@@ -0,0 +1,19 @@
+include = function(relpath){
+       document.write("<script type='text/javascript' src=" + relpath + " charset='UTF-8'></script>");
+}
+//AI004
+include("./../aiext.js");
+//WebCPU
+include("./../webcpu/api.js");
+include("./../webcpu/ext.js");
+include("./../webcpu/api.js");
+include("./../webcpu/decoder.js");
+include("./../webcpu/memory.js");
+include("./../webcpu/instrbas.js");
+include("./../webcpu/instr.js");
+include("./../webcpu/webcpu.js");
+include("./../webcpu/const.js");
+//ELCC
+include("./elcc.js");
+include("./elcexpr.js");
+
index 8510adb..0d3133c 100644 (file)
@@ -15,20 +15,6 @@ BitmapCanvas.prototype = {
                        this.height = this.canvasDOMObject.height;
                        this.bufferImageData = this.canvasContext.getImageData(0, 0, this.width, this.height);
                        this.bmp = this.bufferImageData.data;
-                       console.log(this.bufferImageData);
-                       //
-                       /*
-                       for(var i = 0; i < 100; i += 2){
-                               this.drawLine(0, i, 100, i, 0xffffff, 0);
-                       }
-                       var x0 = 10;
-                       var y0 = 10;
-                       var x1 = 60;
-                       var y1 = 11;
-                       this.drawLine(x0, y0, x1, y1, 0xff0000, 0);
-                       this.drawLine(x1, y1, x0, y0, 0x00ff00, 1);
-                       */
-                       this.flush();
                } else{
                        this.bmp = null;
                        this.canvasContext = null;
index ebf62f6..092e9cb 100644 (file)
@@ -6,6 +6,7 @@ function WebCPU_Instruction(instrID){
        //命令クラス共通部分
        //バックエンドバイナリでの命令先頭バイトのオフセット
        this.binOffset = 0;
+       this.instrID = instrID;
 }
 WebCPU_Instruction.prototype = {
        // loadArguments, execute, toStringが必須。
index a23a2cd..9ccf65a 100644 (file)
@@ -1,23 +1,36 @@
 *WebCPU-VM
-By hikarupsp 2013-2014 for OSECPU-VM
+By [[hikarupsp]] 2013-2014 for OSECPU-VM
 
 **これは何?
-OSECPU-VMのJavaScript実装です。
-JavaScriptは、ほとんどの場合ウェブブラウザさえあれば実行できる言語なので、より多くの環境でOSECPUコードを実行させることができます。
-また、HTML5技術(Canvas)と連携することで、ウェブページに直接OSECPUコードを埋め込むこともできるようになるでしょう。
-これは、テキストを直接転送しているHTMLにとって、データの転送量を削減することにもつながります。
+-OSECPU-VMのJavaScript実装です。
+-テストページ
+--準備中です…
+-Gitリポジトリ
+--http://sourceforge.jp/projects/chnosproject/scm/git/AI004/
+--webcpuディレクトリにすべてが入っています。(index.htmlがフロントエンド)
+--webcpuディレクトリ単体で動作します。elcc(OSECPU用コンパイラ)との関係でリポジトリは統合しました
+-JavaScriptは、ほとんどの場合ウェブブラウザさえあれば実行できる言語なので、より多くの環境でOSECPUコードを実行させることができます。
+-また、HTML5技術(Canvas)と連携することで、ウェブページに直接OSECPUコードを埋め込むこともできるようになるでしょう。
+--これは、テキストを直接転送しているHTMLにとって、データの転送量を削減することにもつながります。
 
 **動作環境
 動作を確認している環境は以下の通りです。(app0023フロントエンドコードテキストのStepInMs実行にて確認。)
 -Chrome (Mac OSX, Windows)
+
+以下の環境でも動作するかもしれません。
 -Safari (Mac OSX, iOS)
 -Browser (Android)
 -InternetExplorer9 (Windows)
 
-**現在の状況は?
--アプリケーションバイナリのフロントエンドコードHex文字列を実行し、その結果を表示することができます。
--実行バイナリをドラッグ&ドロップで直接読み込ませ、実行させることができます(HTML5FileAPI対応ブラウザに限ります)。
--バックエンド命令はほとんどが実装されていますが、APIおよびメモリ関連の一部の命令は未実装です。
+**できるようになったこと
+-フロントエンドコードの実行(decoder.oseを利用)
+-グラフィック関連APIのmode指定の反映(PSET,OR,XOR,AND等)
+-バイナリファイルの直接実行
+--FileAPI対応ブラウザ(Chrome等)が必要です。
+**今はできないこと(できる範囲で実装します)
+-半分くらいのAPI
+--ユーザー入力が必要なAPI
+--メモリ操作が必要なAPI
 
 **使い方は?
 組み込んで使用する方は、index.htmlのサンプルコードを見ていただければ、だいたいはわかると思います。
@@ -35,3 +48,8 @@ Loadボタンを押すことで、バイナリコードが解釈されてWebCPU
 -デバッグモードについて
 デバッグモード時は、実行中のレジスタ情報と現在実行中の命令について詳細を確認しながら実行できます。
 負荷のかかるアプリケーションを実行する際は、デバッグモードを無効にするのがよいでしょう。
+
+**技術情報
+[[hikarupsp_WebCPU-VM_internal]]を参照してください。
+
+
index ed3d54a..e347883 100755 (executable)
@@ -188,6 +188,7 @@ WebCPU.prototype = {
                
                this.memoryPageCounter = 0;
                this.memoryInstructionCounter = 0;
+               this.reset();
        },
        loadFrontEndBinaryText: function(binStr){
                //引数はフロントエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
@@ -324,7 +325,10 @@ WebCPU.prototype = {
                this.memoryPageCounter = 0;
                this.memoryInstructionCounter = 0;
                this.stopFlag = false;
-               //
+               //reset window
+               if(this.API.mainWindowCanvas){
+                       this.API.setMainWindowCanvasDOMObject(this.API.mainWindowCanvas);
+               }
                this.message("<<< Reset >>>\n");
        },
        fetchMemoryNext: function(){
@@ -344,15 +348,37 @@ WebCPU.prototype = {
                this.API.setMainWindowCanvasDOMObject(document.getElementById(id));
        },
        setDebugMessageDOMObject: function(name){
-               this.debugMessageText = document.getElementsByName(name)[0];
+               if(name){
+                       this.debugMessageText = document.getElementsByName(name)[0];
+                       if(!this.debugMessageText){
+                               this.debugMessageText = document.getElementById(name);
+                       }
+               } else{
+                       this.debugMessageText = null;
+               }
                this.setDebugTimer();
        },
        setDebugIntegerRegisterDOMObject: function(name){
-               this.debugIntegerRegisterText = document.getElementsByName(name)[0];
+               if(name){
+                       this.debugIntegerRegisterText = document.getElementsByName(name)[0];
+                       if(!this.debugIntegerRegisterText){
+                               this.debugIntegerRegisterText = document.getElementById(name);
+                       }
+               } else{
+                       this.debugIntegerRegisterText = null;
+               }
                this.setDebugTimer();
        },
        setDebugPointerRegisterDOMObject: function(name){
                this.debugPointerRegisterText = document.getElementsByName(name)[0];
+               if(name){
+                       this.debugPointerRegisterText = document.getElementsByName(name)[0];
+                       if(!this.debugPointerRegisterText){
+                               this.debugPointerRegisterText = document.getElementById(name);
+                       }
+               } else{
+                       this.debugPointerRegisterText = null;
+               }
                this.setDebugTimer();
        },
        setDebugTimer: function(){