diff --git a/public/site.css b/public/site.css index 72d0847..eff7c84 100644 --- a/public/site.css +++ b/public/site.css @@ -4,6 +4,8 @@ border-radius: 4px; padding: 4px; border-color: #ddd; + max-height: 300px; + overflow-y: auto; } .brad { @@ -29,4 +31,5 @@ nav { .btm-btn { margin-bottom: 4px; + margin-top: -14px; } diff --git a/public/vm/Makefile b/public/vm/Makefile new file mode 100644 index 0000000..ea1e733 --- /dev/null +++ b/public/vm/Makefile @@ -0,0 +1,4 @@ +FILES = c0vm.js bytecode-parser.js byte-stream.js opcodes.js index.js + +all: $(FILES) + browserify $(FILES) -o vm.js diff --git a/src/byte-stream.js b/public/vm/byte-stream.js similarity index 100% rename from src/byte-stream.js rename to public/vm/byte-stream.js diff --git a/src/bytecode-parser.js b/public/vm/bytecode-parser.js similarity index 96% rename from src/bytecode-parser.js rename to public/vm/bytecode-parser.js index 35c82de..dd8240b 100644 --- a/src/bytecode-parser.js +++ b/public/vm/bytecode-parser.js @@ -2,7 +2,9 @@ fs = require("fs"); byte_stream = require("./byte-stream"); // This is a simple, kinda hacky bytecode parser for .bc0 files -function getBytes(filename) { +// Now takes in raw bytecode +function getBytes(data) { + /* var data = fs.readFileSync(filename); if (data == null) { @@ -12,6 +14,7 @@ function getBytes(filename) { console.log("Error: " + err); return; } + */ // Data contains our file, but we want it as a string var string_data = data.toString(); @@ -29,6 +32,7 @@ function getBytes(filename) { }); // We now have an array of bytes. That's probably everything we need, right? + console.log(bytes); return bytes; } diff --git a/src/c0vm.js b/public/vm/c0vm.js similarity index 100% rename from src/c0vm.js rename to public/vm/c0vm.js diff --git a/src/cc0.cgi b/public/vm/cc0.cgi similarity index 100% rename from src/cc0.cgi rename to public/vm/cc0.cgi diff --git a/src/index.js b/public/vm/index.js similarity index 77% rename from src/index.js rename to public/vm/index.js index dd3b7a5..b242194 100644 --- a/src/index.js +++ b/public/vm/index.js @@ -9,5 +9,7 @@ c0vm = require("./c0vm.js"); // console.log(file); // console.log(file.function_pool[0].code); -var file = parser.parse("../test/iadd.c0.bc0"); -console.log("Result is " + c0vm.execute(file)); +$("#run").click(function() { + var file = parser.parse($("#bytecode").text); + $("#output").text(c0vm.execute(file)); +}); diff --git a/src/opcodes.js b/public/vm/opcodes.js similarity index 100% rename from src/opcodes.js rename to public/vm/opcodes.js diff --git a/public/vm/vm.js b/public/vm/vm.js new file mode 100644 index 0000000..fee13b5 --- /dev/null +++ b/public/vm/vm.js @@ -0,0 +1,520 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 31) c0_arith_error("Shifting by too many bits"); + this.stack.push(x< 31) c0_arith_error("Shifting by too many bits"); + this.stack.push(x>>y); + break; + + // Operations on local variables + + case op.VLOAD: + this.pc += 2; + var index = this.program[this.pc-1]; + this.stack.push(this.variables[index]); + break; + case op.VSTORE: + this.pc += 2; + var index = this.program[this.pc-1]; + this.variables[index] = this.stack.pop(); + break; + case op.ACONST_NULL: + this.pc++; + this.stack.push(0); + break; + case op.ILDC: + this.pc += 3; + var c1 = this.program[this.pc-2]; + var c2 = this.program[this.pc-1]; + var index = (c1 * 0x1000) + c2; + + this.stack.push(this.file.int_pool[index]); + break; + case op.ALDC: + console.log("Error: I don't know how to handle ALDC yet"); + throw "Error - can't handle ALDC"; + + // Control flow + case op.NOP: + this.pc++; + break; + case op.IF_CMPEQ: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y == x); + break; + case op.IF_CMPNE: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y != x); + break; + case op.IF_CMPLT: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y > x); + break; + case op.IF_CMPGE: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y <= x); + break; + case op.IF_CMPGT: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y < x); + break; + case op.IF_CMPLE: + var y = this.stack.pop(); + var x = this.stack.pop(); + this.doIf(y >= x); + break; + case op.GOTO: + this.doIf(true); + break; + case op.ATHROW: + this.pc++; + c0_user_error(this.stack.pop()); + break; + case op.ASSERT: + this.pc++; + var a = this.stack.pop(); + if (this.stack.pop() == 0) + c0_assertion_failure(a); + break; + + default: + console.log("Error: Unknown opcode\n"); + throw "Error - unknown opcode"; + } + return false; +} + +// Takes in a parsed .bc0 file and runs it +function execute(f) { + console.log("Beginning execution of file " + f); + + var state = new ProgramState(f); + + while (true) { + // I'm not sure how to structure this control flow yet, + // so if anyone has a better idea, let me know + try { + state.step(); + } catch (val) { + return val; + } + + // if (at_breakpoint) { + // save state (maybe in a global in this file?) + // return; + // } + } +} + +exports.execute = execute; + +// opcode definitions + + +},{"./opcodes":5}],4:[function(require,module,exports){ +parser = require("./bytecode-parser"); +c0vm = require("./c0vm.js"); + +// console.log("Reading in sample bytecode file:"); +// console.log(parser.getBytes("../test/test.bc0")); +// console.log("That was the sample bytecode file" + +// " -- it probably took up your whole terminal screen."); +// var file = parser.parse("../test/test.bc0"); +// console.log(file); +// console.log(file.function_pool[0].code); + +$("#run").click(function() { + var file = parser.parse($("#bytecode").text); + $("#output").text(c0vm.execute(file)); +}); + +},{"./bytecode-parser":2,"./c0vm.js":3}],5:[function(require,module,exports){ +/* arithmetic operations */ +exports.IADD = 0x60; +exports.IAND = 0x7E; +exports.IDIV = 0x6C; +exports.IMUL = 0x68; +exports.IOR = 0x80; +exports.IREM = 0x70; +exports.ISHL = 0x78; +exports.ISHR = 0x7A; +exports.ISUB = 0x64; +exports.IXOR = 0x82; + +/* stack operations */ +exports.DUP = 0x59; +exports.POP = 0x57; +exports.SWAP = 0x5F; + +/* memory allocation */ +exports.NEWARRAY = 0xBC; +exports.ARRAYLENGTH = 0xBE; +exports.NEW = 0xBB; + +/* memory access */ +exports.AADDF = 0x62; +exports.AADDS = 0x63; +exports.IMLOAD = 0x2E; +exports.AMLOAD = 0x2F; +exports.IMSTORE = 0x4E; +exports.AMSTORE = 0x4F; +exports.CMLOAD = 0x34; +exports.CMSTORE = 0x55; + +/* local variables */ +exports.VLOAD = 0x15; +exports.VSTORE = 0x36; + +/* constants */ +exports.ACONST_NULL = 0x01; +exports.BIPUSH = 0x10; +exports.ILDC = 0x13; +exports.ALDC = 0x14; + +/* control flow */ +exports.NOP = 0x00; +exports.IF_CMPEQ = 0x9F; +exports.IF_CMPNE = 0xA0; +exports.IF_ICMPLT = 0xA1; +exports.IF_ICMPGE = 0xA2; +exports.IF_ICMPGT = 0xA3; +exports.IF_ICMPLE = 0xA4; +exports.GOTO = 0xA7; +exports.ATHROW = 0xBF; +exports.ASSERT = 0xCF; + +/* function calls and returns */ +exports.INVOKESTATIC = 0xB8; +exports.INVOKENATIVE = 0xB7; +exports.RETURN = 0xB0 + + +exports.lookup_table = { + 0x60: "IADD", + 0x7E: "IAND", + 0x6C: "IDIV", + 0x68: "IMUL", + 0x80: "IOR", + 0x70: "IREM", + 0x78: "ISHL", + 0x7A: "ISHR", + 0x64: "ISUB", + 0x82: "IXOR", + 0x59: "DUP", + 0x57: "POP", + 0x5F: "SWAP", + 0xBC: "NEWARRAY", + 0xBE: "ARRAYLENGTH", + 0xBB: "NEW", + 0x62: "AADDF", + 0x63: "AADDS", + 0x2E: "IMLOAD", + 0x2F: "AMLOAD", + 0x4E: "IMSTORE", + 0x4F: "AMSTORE", + 0x34: "CMLOAD", + 0x55: "CMSTORE", + 0x15: "VLOAD", + 0x36: "VSTORE", + 0x01: "ACONST", + 0x10: "BIPUSH", + 0x13: "ILDC", + 0x14: "ALDC", + 0x00: "NOP", + 0x9F: "IF", + 0xA0: "IF", + 0xA1: "IF", + 0xA2: "IF", + 0xA3: "IF", + 0xA4: "IF", + 0xA7: "GOTO", + 0xBF: "ATHROW", + 0xCF: "ASSERT", + 0xB8: "INVOKESTATIC", + 0xB7: "INVOKENATIVE", + 0xB0: "RETURN" +}; + +},{}],6:[function(require,module,exports){ + +},{}]},{},[3,2,1,5,4]); diff --git a/views/.index.jade.swp b/views/.index.jade.swp deleted file mode 100644 index 8f5d625..0000000 Binary files a/views/.index.jade.swp and /dev/null differ diff --git a/views/index.jade b/views/index.jade index f8bf900..2e1ac1b 100644 --- a/views/index.jade +++ b/views/index.jade @@ -11,22 +11,32 @@ block nav block body .container - .col-md-6 - form - .form-group - label(for="inputCode") Code - button(onclick="compile()" type="button").btn.btn-default.btm-btn.pull-right Compile - #codearea - textarea.code.formControl.sh_c(rows="12" id="inputCode") + .row + .col-md-6 + form + .form-group + label(for="inputCode") Code + button(onclick="compile()" type="button").btn.btn-default.btm-btn.pull-right Compile + #codearea + textarea.code.formControl.sh_c(rows="12" id="inputCode") + + .col-md-6 + p.lbl. + Bytecode + pre#bytecode.panel.panel-default.code.sh_c. +   + .row + .col-md-12 + p.lbl. + Output + button(type="button")#run.btn.btn-default.btm-btn.pull-right Run + pre#output.panel.panel-default.code +   - .col-md-6 - p.lbl. - Bytecode - pre#bytecode.panel.panel-default.code.clearfix.sh_c. -   block script script(type="text/javascript" src="codemirror-compressed.js") + script(type="text/javascript" src="vm/vm.js") script(type='text/javascript'). var cmCodeInput = CodeMirror.fromTextArea($("#inputCode")); @@ -49,4 +59,3 @@ block script jsonpCallback: "callback" }); } -