Compare commits
14 Commits
shyam_ragh
...
mplamann
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e0529a1e0 | ||
|
|
44f10cb5c6 | ||
|
|
d035346d2b | ||
|
|
5bee4d90c5 | ||
|
|
c742d5ed74 | ||
| 609b6e17d4 | |||
| 81a08cb9f8 | |||
| f4b3c06f79 | |||
| 88b006cbcc | |||
| ddf1d00f1b | |||
| 739005289e | |||
|
|
349fd6ff78 | ||
|
|
6138821c3a | ||
|
|
d39df5314d |
BIN
instructions/Thumbs.db
Normal file
BIN
instructions/Thumbs.db
Normal file
Binary file not shown.
0
logo.png
Executable file → Normal file
0
logo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 345 KiB |
0
progress_report/lit_review.tex
Executable file → Normal file
0
progress_report/lit_review.tex
Executable file → Normal file
0
proposal/letter.pdf
Executable file → Normal file
0
proposal/letter.pdf
Executable file → Normal file
0
proposal/letter.tex
Executable file → Normal file
0
proposal/letter.tex
Executable file → Normal file
0
proposal/proposal.pdf
Executable file → Normal file
0
proposal/proposal.pdf
Executable file → Normal file
0
proposal/proposal.tex
Executable file → Normal file
0
proposal/proposal.tex
Executable file → Normal file
@@ -1,4 +1,7 @@
|
||||
FILES = c0vm.js bytecode-parser.js byte-stream.js opcodes.js index.js
|
||||
FILES = c0vm.js bytecode-parser.js byte-stream.js opcodes.js c0ffi.js index.js
|
||||
|
||||
all: $(FILES)
|
||||
browserify $(FILES) -o vm.js
|
||||
|
||||
clean:
|
||||
rm -f vm.js
|
||||
|
||||
0
public/vm/byte-stream.js
Executable file → Normal file
0
public/vm/byte-stream.js
Executable file → Normal file
@@ -4,21 +4,8 @@ byte_stream = require("./byte-stream");
|
||||
// This is a simple, kinda hacky bytecode parser for .bc0 files
|
||||
// Now takes in raw bytecode
|
||||
function getBytes(data) {
|
||||
/*
|
||||
var data = fs.readFileSync(filename);
|
||||
|
||||
if (data == null) {
|
||||
if (err["code"] === "ENOENT")
|
||||
console.log("Error: file " + filename + " does not exist.");
|
||||
else
|
||||
console.log("Error: " + err);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// Data contains our file, but we want it as a string
|
||||
var string_data = data.toString();
|
||||
console.log(string_data);
|
||||
|
||||
// Strip all the comments for easier parsing
|
||||
var without_comments = string_data.replace(new RegExp("#.*", "gi"), "");
|
||||
@@ -33,15 +20,37 @@ function getBytes(data) {
|
||||
});
|
||||
|
||||
// We now have an array of bytes. That's probably everything we need, right?
|
||||
console.log(bytes);
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
function getLineNumbers(data) {
|
||||
var string_data = data.toString();
|
||||
|
||||
// Strip all the comments for easier parsing
|
||||
var without_comments = string_data.replace(new RegExp("#.*", "gi"), "");
|
||||
|
||||
// Each byte should now be a pair of two hex digits.
|
||||
// Put all these in an array.
|
||||
var lines = without_comments.split("\n");
|
||||
var line_numbers = [];
|
||||
for (var line_number = 0; line_number < lines.length; line_number++ ) {
|
||||
lines[line_number].replace(
|
||||
new RegExp("([0123456789ABCDEF][0123456789ABCDEF])", "gi"),
|
||||
function(next_byte) {
|
||||
// +1 because lines start at 1, for some weird reason.
|
||||
// Who doesn't start counting at 0?
|
||||
line_numbers.push(line_number+1);
|
||||
});
|
||||
}
|
||||
return line_numbers;
|
||||
}
|
||||
|
||||
var FunctionInfo = function (stream) {
|
||||
this.num_args = stream.get_u2();
|
||||
this.num_vars = stream.get_u2();
|
||||
this.code_length = stream.get_u2();
|
||||
this.code_byte_offset = stream.index;
|
||||
this.code = stream.get_bytes(this.code_length);
|
||||
}
|
||||
|
||||
@@ -50,8 +59,9 @@ var NativeInfo = function (stream) {
|
||||
this.function_table_index = stream.get_u2();
|
||||
}
|
||||
|
||||
var Bc0File = function (filename) {
|
||||
var file = getBytes(filename);
|
||||
var Bc0File = function (bytecode) {
|
||||
var file = getBytes(bytecode);
|
||||
this.line_numbers = getLineNumbers(bytecode);
|
||||
var stream = new byte_stream.ByteStream(file);
|
||||
|
||||
var magic = stream.get_u4();
|
||||
@@ -90,6 +100,7 @@ var Bc0File = function (filename) {
|
||||
this.function_pool = [];
|
||||
for (var i = 0; i < this.function_count; i++) {
|
||||
this.function_pool.push(new FunctionInfo(stream));
|
||||
this.function_pool[i].function_id = i;
|
||||
}
|
||||
|
||||
this.native_count = stream.get_u2();
|
||||
@@ -108,9 +119,50 @@ Bc0File.prototype.string_from_index = function (i) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function parse(filename) {
|
||||
return new Bc0File(filename);
|
||||
Bc0File.prototype.line_for_indices = function(function_index, byte_offset) {
|
||||
var offset_in_file = this.function_pool[function_index].code_byte_offset +
|
||||
byte_offset;
|
||||
return this.line_numbers[offset_in_file];
|
||||
}
|
||||
|
||||
Bc0File.prototype.indicies_for_line = function(line) {
|
||||
// Performs a linear search through the (bytecode to line number) map
|
||||
// to find the bytecode offsets corresponding to a line number
|
||||
var function_index = 0;
|
||||
while (function_index < this.function_pool.length - 1) {
|
||||
var function_start = this.function_pool[function_index + 1].code_byte_offset;
|
||||
if (this.line_numbers[function_start] > line) break;
|
||||
function_start++;
|
||||
}
|
||||
|
||||
// function_index should now be set to the index of the function containing our line
|
||||
var f = this.function_pool[function_index];
|
||||
var offset = 0;
|
||||
while (offset < f.code.length - 1) {
|
||||
if (this.line_numbers[f.code_byte_offset + offset] > line) break;
|
||||
offset++;
|
||||
}
|
||||
return [function_index, offset];
|
||||
}
|
||||
|
||||
function parse(bytecode) {
|
||||
return new Bc0File(bytecode);
|
||||
}
|
||||
|
||||
function parseFile(filename) {
|
||||
var data = fs.readFileSync(filename);
|
||||
|
||||
if (data == null) {
|
||||
if (err["code"] === "ENOENT")
|
||||
console.log("Error: file " + filename + " does not exist.");
|
||||
else
|
||||
console.log("Error: " + err);
|
||||
return;
|
||||
}
|
||||
|
||||
return parse(data);
|
||||
}
|
||||
|
||||
exports.getBytes = getBytes;
|
||||
exports.parse = parse;
|
||||
exports.parseFile = parseFile;
|
||||
|
||||
@@ -108,3 +108,46 @@ exports.NATIVE_STRING_TERMINATED = 92
|
||||
exports.NATIVE_STRING_TO_CHARARRAY = 93
|
||||
exports.NATIVE_STRING_TOLOWER = 94
|
||||
|
||||
callbacks = {};
|
||||
callbacks[exports.NATIVE_STRING_LENGTH] =
|
||||
function(args) {
|
||||
return args[0].length;
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_STRING_TO_CHARARRAY] =
|
||||
function(args, vm) {
|
||||
var address = vm.heap.length;
|
||||
vm.heap.push(args[0].length+1);
|
||||
vm.heap.push(1);
|
||||
for (var i = 0; i < args[0].length; i++) {
|
||||
vm.heap.push(args[0][i]);
|
||||
}
|
||||
vm.heap.push(0);
|
||||
return address;
|
||||
};
|
||||
|
||||
|
||||
callbacks[exports.NATIVE_STRING_FROM_CHARARRAY] =
|
||||
function(args, vm) {
|
||||
var i = args[0] + 2;
|
||||
var result = "";
|
||||
while (vm.heap[i] !== 0) {
|
||||
result += vm.heap[i];
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_CHAR_CHR] =
|
||||
function(args) {
|
||||
return String.fromCharCode(args[0]);
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_CHAR_ORD] =
|
||||
function(args) {
|
||||
if (typeof args[0] == "string")
|
||||
return args[0].charCodeAt(0);
|
||||
return args[0];
|
||||
};
|
||||
|
||||
exports.default_callbacks = callbacks;
|
||||
|
||||
118
public/vm/c0vm.js
Executable file → Normal file
118
public/vm/c0vm.js
Executable file → Normal file
@@ -42,6 +42,7 @@ var StackFrame = function(file, f) {
|
||||
this.stack = [];
|
||||
this.pc = 0;
|
||||
this.program = f.code;
|
||||
this.function_id = f.function_id;
|
||||
this.variables = [];
|
||||
for (var i = 0; i < f.num_vars; i++)
|
||||
this.variables.push(0);
|
||||
@@ -69,6 +70,8 @@ var ProgramState = function(parsed_file, callback_dict) {
|
||||
}
|
||||
}
|
||||
|
||||
this.breakpoints = [];
|
||||
|
||||
// Memory is just a big array of bytes, right?
|
||||
// "Allocation" is appending onto this array
|
||||
// A pointer to memory is an index into this array.
|
||||
@@ -112,9 +115,10 @@ ProgramState.prototype.doIf = function(f) {
|
||||
}
|
||||
|
||||
ProgramState.prototype.step = function() {
|
||||
this.maintain_line_numbers();
|
||||
var opcode = this.frame.program[this.frame.pc]
|
||||
log("0x" + this.frame.pc.toString(16) + " Running opcode " +
|
||||
op.lookup_table[opcode]);
|
||||
op.lookup_table[opcode] + " at line " + this.bytecode_line);
|
||||
switch (opcode) {
|
||||
// Stack manipulation
|
||||
case op.POP:
|
||||
@@ -341,7 +345,7 @@ ProgramState.prototype.step = function() {
|
||||
}
|
||||
log("Calling native function with index " + index + " with arguments " +
|
||||
arg_array);
|
||||
this.push(native_function(arg_array));
|
||||
this.push(native_function(arg_array, this));
|
||||
break;
|
||||
|
||||
// Memory allocation operations:
|
||||
@@ -470,8 +474,89 @@ ProgramState.prototype.step = function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Takes in a parsed .bc0 file and runs it
|
||||
function execute(file, callbacks, v) {
|
||||
ProgramState.prototype.maintain_line_numbers = function() {
|
||||
this.bytecode_line = this.file.line_for_indices(this.frame.function_id,
|
||||
this.frame.pc);
|
||||
// this.c0_line = SOMEHOW GET THE LINE IN THE c0 FILE
|
||||
}
|
||||
|
||||
ProgramState.prototype.remove_breakpoint = function(opcode_index) {
|
||||
if (opcode_index < 0){
|
||||
console.log("Error: negative opcode_index" + opcode_index.toString());
|
||||
throw "Error - negative opcode index";
|
||||
}
|
||||
else if (opcode_index >= this.frame.program.length) {
|
||||
console.log("Error: opcode index larger than max index:"
|
||||
+ opcode_index.toString());
|
||||
throw "Error - opcode index too large";
|
||||
}
|
||||
for (i = 0; i < this.breakpoints.length; i++) {
|
||||
if (this.breakpoints[i][1] == opcode_index){
|
||||
var index = i;
|
||||
array.splice(index,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("Error: non-breakpoint opcode index" + opcode_index.toString());
|
||||
throw "Error - non-breakpoint opcode index";
|
||||
}
|
||||
|
||||
ProgramState.prototype.set_breakpoint = function(function_index, opcode_index) {
|
||||
if (opcode_index < 0) {
|
||||
console.log("Error: negative opcode_index" + opcode_index.toString());
|
||||
throw "Error - negative opcode index";
|
||||
}
|
||||
else if (opcode_index >= this.frame.program.length) {
|
||||
console.log("Error: opcode index larger than max index:"
|
||||
+ opcode_index.toString());
|
||||
throw "Error - opcode index too large";
|
||||
}
|
||||
this.breakpoints.push([function_index, opcode_index]);
|
||||
}
|
||||
|
||||
ProgramState.prototype.set_breakpoint_bytecode_line = function(line) {
|
||||
var indicies = this.file.indicies_for_line(line);
|
||||
if (indicies === null || indicies.length < 2) {
|
||||
console.log("Error - indicies_for_line returned an invalid result.");
|
||||
}
|
||||
this.set_breakpoint(indicies[0], indicies[1]);
|
||||
}
|
||||
|
||||
ProgramState.prototype.run = function() {
|
||||
while (true) {
|
||||
for (var i = 0; i < this.breakpoints.length; i++) {
|
||||
var breakpoint = this.breakpoints[i];
|
||||
|
||||
if (this.frame.function_id == breakpoint[0] &&
|
||||
this.frame.pc == breakpoint[1] &&
|
||||
this.stopped_at !== breakpoint) {
|
||||
log("Breakpoint reached!");
|
||||
this.stopped_at = breakpoint;
|
||||
|
||||
this.maintain_line_numbers();
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
this.stopped_at = undefined;
|
||||
|
||||
var val = this.step();
|
||||
if (val !== undefined) return val;
|
||||
|
||||
if (verbose) {
|
||||
console.log("Machine this:");
|
||||
console.log(" Current Stack Frame:");
|
||||
console.log(" Stack: " + this.frame.stack);
|
||||
console.log(" PC: " + this.frame.pc);
|
||||
console.log(" Vars: " + this.frame.variables);
|
||||
// console.log(" Code: " + this.frame.program);
|
||||
console.log(" Heap: " + this.heap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initialize_vm(file, callbacks, v) {
|
||||
verbose = typeof v !== 'undefined' ? v : true;
|
||||
log("Initializing with file " + file);
|
||||
|
||||
@@ -481,25 +566,14 @@ function execute(file, callbacks, v) {
|
||||
|
||||
log("Beginning execution");
|
||||
|
||||
while (true) {
|
||||
var val = state.step();
|
||||
if (val !== undefined) return val;
|
||||
return state;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
console.log("Machine state:");
|
||||
console.log(" Current Stack Frame:");
|
||||
console.log(" Stack: " + state.frame.stack);
|
||||
console.log(" PC: " + state.frame.pc);
|
||||
console.log(" Vars: " + state.frame.variables);
|
||||
// console.log(" Code: " + state.frame.program);
|
||||
console.log(" Heap: " + state.heap);
|
||||
}
|
||||
|
||||
// if (at_breakpoint) {
|
||||
// save state (maybe in a global in this file?)
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
// Takes in a parsed .bc0 file and runs it
|
||||
function execute(file, callbacks, v) {
|
||||
var state = initialize_vm(file, callbacks, v);
|
||||
return state.run();
|
||||
}
|
||||
|
||||
exports.execute = execute;
|
||||
exports.initialize_vm = initialize_vm;
|
||||
|
||||
0
public/vm/cc0.cgi
Executable file → Normal file
0
public/vm/cc0.cgi
Executable file → Normal file
@@ -16,7 +16,7 @@ function print(arg) {
|
||||
$("#output").append(arg);
|
||||
}
|
||||
|
||||
callbacks = {};
|
||||
callbacks = c0ffi.default_callbacks;
|
||||
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||
print(args[0]);
|
||||
print("<br />");
|
||||
@@ -33,6 +33,9 @@ console.log(callbacks);
|
||||
|
||||
$("#run").click(function() {
|
||||
var input = $("#bytecode").html().replace(/(\r\n|\n|\r)/gm,"");
|
||||
|
||||
$("#output").text("");
|
||||
|
||||
var file = parser.parse($("#bytecode").text());
|
||||
print("<br />");
|
||||
print(c0vm.execute(file, callbacks));
|
||||
|
||||
113
public/vm/vm.js
113
public/vm/vm.js
@@ -131,6 +131,7 @@ var Bc0File = function (filename) {
|
||||
this.function_pool = [];
|
||||
for (var i = 0; i < this.function_count; i++) {
|
||||
this.function_pool.push(new FunctionInfo(stream));
|
||||
this.function_pool[i].function_id = i;
|
||||
}
|
||||
|
||||
this.native_count = stream.get_u2();
|
||||
@@ -267,6 +268,49 @@ exports.NATIVE_STRING_TERMINATED = 92
|
||||
exports.NATIVE_STRING_TO_CHARARRAY = 93
|
||||
exports.NATIVE_STRING_TOLOWER = 94
|
||||
|
||||
callbacks = {};
|
||||
callbacks[exports.NATIVE_STRING_LENGTH] =
|
||||
function(args) {
|
||||
return args[0].length;
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_STRING_TO_CHARARRAY] =
|
||||
function(args, vm) {
|
||||
var address = vm.heap.length;
|
||||
vm.heap.push(args[0].length+1);
|
||||
vm.heap.push(1);
|
||||
for (var i = 0; i < args[0].length; i++) {
|
||||
vm.heap.push(args[0][i]);
|
||||
}
|
||||
vm.heap.push(0);
|
||||
return address;
|
||||
};
|
||||
|
||||
|
||||
callbacks[exports.NATIVE_STRING_FROM_CHARARRAY] =
|
||||
function(args, vm) {
|
||||
var i = args[0] + 2;
|
||||
var result = "";
|
||||
while (vm.heap[i] !== 0) {
|
||||
result += vm.heap[i];
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_CHAR_CHR] =
|
||||
function(args) {
|
||||
return String.fromCharCode(args[0]);
|
||||
};
|
||||
|
||||
callbacks[exports.NATIVE_CHAR_ORD] =
|
||||
function(args) {
|
||||
if (typeof args[0] == "string")
|
||||
return args[0].charCodeAt(0);
|
||||
return args[0];
|
||||
};
|
||||
|
||||
exports.default_callbacks = callbacks;
|
||||
|
||||
},{}],4:[function(require,module,exports){
|
||||
op = require("./opcodes");
|
||||
@@ -299,7 +343,6 @@ function i32_to_array(i32) {
|
||||
((i32 >> 8) & 0xFF),
|
||||
((i32 >> 16) & 0xFF),
|
||||
((i32 >> 24) & 0xFF)];
|
||||
|
||||
}
|
||||
|
||||
function array_to_i32(array) {
|
||||
@@ -314,6 +357,7 @@ var StackFrame = function(file, f) {
|
||||
this.stack = [];
|
||||
this.pc = 0;
|
||||
this.program = f.code;
|
||||
this.function_id = f.function_id;
|
||||
this.variables = [];
|
||||
for (var i = 0; i < f.num_vars; i++)
|
||||
this.variables.push(0);
|
||||
@@ -334,13 +378,15 @@ var ProgramState = function(parsed_file, callback_dict) {
|
||||
try {
|
||||
this.natives[i] = callback_dict[i];
|
||||
} catch (key_not_found) {
|
||||
this.natives[i] = function (arg) {
|
||||
this.natives[i] = function (arg) {
|
||||
console.log("Native function " + name + " called, ran method stub.");
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.breakpoints = [];
|
||||
|
||||
// Memory is just a big array of bytes, right?
|
||||
// "Allocation" is appending onto this array
|
||||
// A pointer to memory is an index into this array.
|
||||
@@ -409,7 +455,7 @@ ProgramState.prototype.step = function() {
|
||||
case op.BIPUSH:
|
||||
this.frame.pc += 2;
|
||||
var val = this.frame.program[this.frame.pc-1];
|
||||
|
||||
|
||||
// Do sign extension if necessary
|
||||
if ((val & 0x80) != 0)
|
||||
val = -0x80 + (val & 0x7F);
|
||||
@@ -611,9 +657,9 @@ ProgramState.prototype.step = function() {
|
||||
};
|
||||
console.log("Unknown native function index " + f.function_table_index);
|
||||
}
|
||||
log("Calling native function with index " + index + " with arguments " +
|
||||
log("Calling native function with index " + index + " with arguments " +
|
||||
arg_array);
|
||||
this.push(native_function(arg_array));
|
||||
this.push(native_function(arg_array, this));
|
||||
break;
|
||||
|
||||
// Memory allocation operations:
|
||||
@@ -623,7 +669,7 @@ ProgramState.prototype.step = function() {
|
||||
var address = this.heap.length;
|
||||
|
||||
for (var i = 0; i < size; i++) this.heap.push(0);
|
||||
|
||||
|
||||
this.push(address);
|
||||
this.frame.pc += 2;
|
||||
break;
|
||||
@@ -636,7 +682,7 @@ ProgramState.prototype.step = function() {
|
||||
|
||||
this.heap.push(num_elements);
|
||||
this.heap.push(size);
|
||||
|
||||
|
||||
for (var i = 0; i < num_elements; i++) {
|
||||
for (var j = 0; j < size; j++)
|
||||
this.heap.push(0);
|
||||
@@ -742,8 +788,11 @@ ProgramState.prototype.step = function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Takes in a parsed .bc0 file and runs it
|
||||
function execute(file, callbacks, v) {
|
||||
ProgramState.prototype.set_breakpoint = function(function_index, opcode_index) {
|
||||
this.breakpoints.push([function_index, opcode_index]);
|
||||
}
|
||||
|
||||
function initialize_vm(file, callbacks, v) {
|
||||
verbose = typeof v !== 'undefined' ? v : true;
|
||||
log("Initializing with file " + file);
|
||||
|
||||
@@ -752,29 +801,48 @@ function execute(file, callbacks, v) {
|
||||
if (verbose) log(file);
|
||||
|
||||
log("Beginning execution");
|
||||
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function run_vm(vm) {
|
||||
while (true) {
|
||||
var val = state.step();
|
||||
for (breakpoint in vm.breakpoints) {
|
||||
if (vm.frame.function_id == breakpoint[0] &&
|
||||
vm.frame.pc == breakpoint[1]) {
|
||||
console.log("Breakpoint reached!");
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
|
||||
var val = vm.step();
|
||||
if (val !== undefined) return val;
|
||||
|
||||
if (verbose) {
|
||||
console.log("Machine state:");
|
||||
console.log("Machine vm:");
|
||||
console.log(" Current Stack Frame:");
|
||||
console.log(" Stack: " + state.frame.stack);
|
||||
console.log(" PC: " + state.frame.pc);
|
||||
console.log(" Vars: " + state.frame.variables);
|
||||
// console.log(" Code: " + state.frame.program);
|
||||
console.log(" Heap: " + state.heap);
|
||||
console.log(" Stack: " + vm.frame.stack);
|
||||
console.log(" PC: " + vm.frame.pc);
|
||||
console.log(" Vars: " + vm.frame.variables);
|
||||
// console.log(" Code: " + vm.frame.program);
|
||||
console.log(" Heap: " + vm.heap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (at_breakpoint) {
|
||||
// save state (maybe in a global in this file?)
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
// Takes in a parsed .bc0 file and runs it
|
||||
function execute(file, callbacks, v) {
|
||||
var state = initialize_vm(file, callbacks, v);
|
||||
return run_vm(state);
|
||||
}
|
||||
|
||||
exports.execute = execute;
|
||||
exports.initialize_vm = initialize_vm;
|
||||
exports.run_vm = run_vm;
|
||||
|
||||
},{"./opcodes":6}],5:[function(require,module,exports){
|
||||
parser = require("./bytecode-parser");
|
||||
@@ -795,7 +863,7 @@ function print(arg) {
|
||||
$("#output").append(arg);
|
||||
}
|
||||
|
||||
callbacks = {};
|
||||
callbacks = c0ffi.default_callbacks;
|
||||
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||
print(args[0]);
|
||||
print("<br />");
|
||||
@@ -812,6 +880,9 @@ console.log(callbacks);
|
||||
|
||||
$("#run").click(function() {
|
||||
var input = $("#bytecode").html().replace(/(\r\n|\n|\r)/gm,"");
|
||||
|
||||
$("#output").text("");
|
||||
|
||||
var file = parser.parse($("#bytecode").text());
|
||||
print("<br />");
|
||||
print(c0vm.execute(file, callbacks));
|
||||
@@ -926,4 +997,4 @@ exports.lookup_table = {
|
||||
|
||||
},{}],7:[function(require,module,exports){
|
||||
|
||||
},{}]},{},[4,2,1,6,5]);
|
||||
},{}]},{},[4,2,1,6,3,5]);
|
||||
|
||||
110
src/c0ffi.js
110
src/c0ffi.js
@@ -1,110 +0,0 @@
|
||||
exports.NATIVE_FADD = 0
|
||||
exports.NATIVE_FDIV = 1
|
||||
exports.NATIVE_FLESS = 2
|
||||
exports.NATIVE_FMUL = 3
|
||||
exports.NATIVE_FSUB = 4
|
||||
exports.NATIVE_FTOI = 5
|
||||
exports.NATIVE_ITOF = 6
|
||||
exports.NATIVE_PRINT_FPT = 7
|
||||
exports.NATIVE_PRINT_HEX = 8
|
||||
exports.NATIVE_PRINT_INT = 9
|
||||
|
||||
/* args */
|
||||
exports.NATIVE_ARGS_FLAG = 10
|
||||
exports.NATIVE_ARGS_INT = 11
|
||||
exports.NATIVE_ARGS_PARSE = 12
|
||||
exports.NATIVE_ARGS_STRING = 13
|
||||
|
||||
/* conio */
|
||||
exports.NATIVE_EOF = 14
|
||||
exports.NATIVE_FLUSH = 15
|
||||
exports.NATIVE_PRINT = 16
|
||||
exports.NATIVE_PRINTBOOL = 17
|
||||
exports.NATIVE_PRINTCHAR = 18
|
||||
exports.NATIVE_PRINTINT = 19
|
||||
exports.NATIVE_PRINTLN = 20
|
||||
exports.NATIVE_READLINE = 21
|
||||
|
||||
/* curses */
|
||||
exports.NATIVE_C_ADDCH = 22
|
||||
exports.NATIVE_C_CBREAK = 23
|
||||
exports.NATIVE_C_CURS_SET = 24
|
||||
exports.NATIVE_C_DELCH = 25
|
||||
exports.NATIVE_C_ENDWIN = 26
|
||||
exports.NATIVE_C_ERASE = 27
|
||||
exports.NATIVE_C_GETCH = 28
|
||||
exports.NATIVE_C_INITSCR = 29
|
||||
exports.NATIVE_C_KEYPAD = 30
|
||||
exports.NATIVE_C_MOVE = 31
|
||||
exports.NATIVE_C_NOECHO = 32
|
||||
exports.NATIVE_C_REFRESH = 33
|
||||
exports.NATIVE_C_SUBWIN = 34
|
||||
exports.NATIVE_C_WADDCH = 35
|
||||
exports.NATIVE_C_WADDSTR = 36
|
||||
exports.NATIVE_C_WCLEAR = 37
|
||||
exports.NATIVE_C_WERASE = 38
|
||||
exports.NATIVE_C_WMOVE = 39
|
||||
exports.NATIVE_C_WREFRESH = 40
|
||||
exports.NATIVE_C_WSTANDEND = 41
|
||||
exports.NATIVE_C_WSTANDOUT = 42
|
||||
exports.NATIVE_CC_GETBEGX = 43
|
||||
exports.NATIVE_CC_GETBEGY = 44
|
||||
exports.NATIVE_CC_GETMAXX = 45
|
||||
exports.NATIVE_CC_GETMAXY = 46
|
||||
exports.NATIVE_CC_GETX = 47
|
||||
exports.NATIVE_CC_GETY = 48
|
||||
exports.NATIVE_CC_HIGHLIGHT = 49
|
||||
exports.NATIVE_CC_KEY_IS_BACKSPACE = 50
|
||||
exports.NATIVE_CC_KEY_IS_DOWN = 51
|
||||
exports.NATIVE_CC_KEY_IS_ENTER = 52
|
||||
exports.NATIVE_CC_KEY_IS_LEFT = 53
|
||||
exports.NATIVE_CC_KEY_IS_RIGHT = 54
|
||||
exports.NATIVE_CC_KEY_IS_UP = 55
|
||||
exports.NATIVE_CC_WBOLDOFF = 56
|
||||
exports.NATIVE_CC_WBOLDON = 57
|
||||
exports.NATIVE_CC_WDIMOFF = 58
|
||||
exports.NATIVE_CC_WDIMON = 59
|
||||
exports.NATIVE_CC_WREVERSEOFF = 60
|
||||
exports.NATIVE_CC_WREVERSEON = 61
|
||||
exports.NATIVE_CC_WUNDEROFF = 62
|
||||
exports.NATIVE_CC_WUNDERON = 63
|
||||
|
||||
/* file */
|
||||
exports.NATIVE_FILE_CLOSE = 64
|
||||
exports.NATIVE_FILE_CLOSED = 65
|
||||
exports.NATIVE_FILE_EOF = 66
|
||||
exports.NATIVE_FILE_READ = 67
|
||||
exports.NATIVE_FILE_READLINE = 68
|
||||
|
||||
/* img */
|
||||
exports.NATIVE_IMAGE_CLONE = 69
|
||||
exports.NATIVE_IMAGE_CREATE = 70
|
||||
exports.NATIVE_IMAGE_DATA = 71
|
||||
exports.NATIVE_IMAGE_DESTROY = 72
|
||||
exports.NATIVE_IMAGE_HEIGHT = 73
|
||||
exports.NATIVE_IMAGE_LOAD = 74
|
||||
exports.NATIVE_IMAGE_SAVE = 75
|
||||
exports.NATIVE_IMAGE_SUBIMAGE = 76
|
||||
exports.NATIVE_IMAGE_WIDTH = 77
|
||||
|
||||
/* parse */
|
||||
exports.NATIVE_PARSE_BOOL = 78
|
||||
exports.NATIVE_PARSE_INT = 79
|
||||
|
||||
/* string */
|
||||
exports.NATIVE_CHAR_CHR = 80
|
||||
exports.NATIVE_CHAR_ORD = 81
|
||||
exports.NATIVE_STRING_CHARAT = 82
|
||||
exports.NATIVE_STRING_COMPARE = 83
|
||||
exports.NATIVE_STRING_EQUAL = 84
|
||||
exports.NATIVE_STRING_FROM_CHARARRAY = 85
|
||||
exports.NATIVE_STRING_FROMBOOL = 86
|
||||
exports.NATIVE_STRING_FROMCHAR = 87
|
||||
exports.NATIVE_STRING_FROMINT = 88
|
||||
exports.NATIVE_STRING_JOIN = 89
|
||||
exports.NATIVE_STRING_LENGTH = 90
|
||||
exports.NATIVE_STRING_SUB = 91
|
||||
exports.NATIVE_STRING_TERMINATED = 92
|
||||
exports.NATIVE_STRING_TO_CHARARRAY = 93
|
||||
exports.NATIVE_STRING_TOLOWER = 94
|
||||
|
||||
0
test/abort.c0.ex
Executable file → Normal file
0
test/abort.c0.ex
Executable file → Normal file
0
test/arith.c0.ex
Executable file → Normal file
0
test/arith.c0.ex
Executable file → Normal file
0
test/arrays.c0.ex
Executable file → Normal file
0
test/arrays.c0.ex
Executable file → Normal file
0
test/dsquared.c0.ex
Executable file → Normal file
0
test/dsquared.c0.ex
Executable file → Normal file
0
test/easyMath.c0.ex
Executable file → Normal file
0
test/easyMath.c0.ex
Executable file → Normal file
0
test/hellosir.c0.ex
Executable file → Normal file
0
test/hellosir.c0.ex
Executable file → Normal file
0
test/iadd.c0
Executable file → Normal file
0
test/iadd.c0
Executable file → Normal file
0
test/iadd.c0.bc0
Executable file → Normal file
0
test/iadd.c0.bc0
Executable file → Normal file
0
test/iadd.c0.ex
Executable file → Normal file
0
test/iadd.c0.ex
Executable file → Normal file
0
test/ishr.c0.ex
Executable file → Normal file
0
test/ishr.c0.ex
Executable file → Normal file
0
test/isqrt.c0.ex
Executable file → Normal file
0
test/isqrt.c0.ex
Executable file → Normal file
0
test/mid.c0.ex
Executable file → Normal file
0
test/mid.c0.ex
Executable file → Normal file
0
test/moreArrays.c0.ex
Executable file → Normal file
0
test/moreArrays.c0.ex
Executable file → Normal file
0
test/piazza1.c0.ex
Executable file → Normal file
0
test/piazza1.c0.ex
Executable file → Normal file
0
test/sample2.5.c0.ex
Executable file → Normal file
0
test/sample2.5.c0.ex
Executable file → Normal file
0
test/strings.c0.ex
Executable file → Normal file
0
test/strings.c0.ex
Executable file → Normal file
0
test/structs.c0.ex
Executable file → Normal file
0
test/structs.c0.ex
Executable file → Normal file
0
test/testError.c0.ex
Executable file → Normal file
0
test/testError.c0.ex
Executable file → Normal file
0
test/testif.c0.ex
Executable file → Normal file
0
test/testif.c0.ex
Executable file → Normal file
@@ -1,8 +1,9 @@
|
||||
parser = require("../src/bytecode-parser.js");
|
||||
c0vm = require("../src/c0vm.js");
|
||||
c0ffi = require("../src/c0ffi.js");
|
||||
parser = require("../public/vm/bytecode-parser.js");
|
||||
c0vm = require("../public/vm/c0vm.js");
|
||||
c0ffi = require("../public/vm/c0ffi.js");
|
||||
|
||||
var callbacks = {}
|
||||
var callbacks = c0ffi.default_callbacks;
|
||||
console.log("Initial callbacks: " + callbacks[c0ffi.NATIVE_STRING_LENGTH](["hi"]));
|
||||
var printout = "";
|
||||
|
||||
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||
@@ -20,33 +21,9 @@ callbacks[c0ffi.NATIVE_PRINTLN] = function(args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
callbacks[c0ffi.NATIVE_STRING_LENGTH] = function(args) {
|
||||
return args[0].length;
|
||||
}
|
||||
|
||||
callbacks[c0ffi.NATIVE_STRING_TO_CHARARRAY] = function(args) {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
callbacks[c0ffi.NATIVE_STRING_FROM_CHARARRAY] = function(args) {
|
||||
console.log("string_from_chararray: " + args);
|
||||
return args[0];
|
||||
}
|
||||
|
||||
callbacks[c0ffi.NATIVE_CHAR_CHR] = function(args) {
|
||||
return String.fromCharCode(args[0]);
|
||||
}
|
||||
|
||||
callbacks[c0ffi.NATIVE_CHAR_ORD] = function(args) {
|
||||
console.log("native_car_ord: " + args);
|
||||
if (typeof args[0] == "string")
|
||||
return args[0].charCodeAt(0);
|
||||
return args[0];
|
||||
}
|
||||
|
||||
function doTest(filename, expected_result) {
|
||||
return function(test) {
|
||||
var result = c0vm.execute(parser.parse(filename), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile(filename), callbacks, false);
|
||||
test.ok(result == expected_result,
|
||||
filename + " - did not get expected result " + expected_result +
|
||||
", instead got " + result);
|
||||
@@ -58,7 +35,7 @@ exports.testIADD = doTest("iadd.c0.bc0", -2);
|
||||
|
||||
exports.testPrint = function(test) {
|
||||
printout = "";
|
||||
var result = c0vm.execute(parser.parse("test.bc0"), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile("test.bc0"), callbacks, false);
|
||||
test.ok(printout == "Hello, world.\nYou don't look so good.\n",
|
||||
"test.bc0 - Did not print to screen correctly: output was " + printout);
|
||||
test.done();
|
||||
@@ -73,7 +50,7 @@ exports.testMID = doTest("mid.c0.bc0", 155);
|
||||
// This one should throw an exception because an assertion fails
|
||||
exports.testSample25 = function(test) {
|
||||
test.throws(function () {
|
||||
c0vm.execute(parser.parse("sample2.5.c0.bc0"), callbacks, false)
|
||||
c0vm.execute(parser.parseFile("sample2.5.c0.bc0"), callbacks, false)
|
||||
});
|
||||
test.done();
|
||||
}
|
||||
@@ -84,14 +61,14 @@ exports.testDSQUARED = doTest("dsquared.c0.bc0", 17068);
|
||||
|
||||
exports.testArrays = function(test) {
|
||||
test.throws(function () {
|
||||
c0vm.execute(parser.parse("arrays.c0.bc0"), callbacks, false)
|
||||
c0vm.execute(parser.parseFile("arrays.c0.bc0"), callbacks, false)
|
||||
});
|
||||
test.done();
|
||||
}
|
||||
|
||||
exports.testMoreArray = function(test) {
|
||||
printout = "";
|
||||
var result = c0vm.execute(parser.parse("moreArrays.c0.bc0"), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile("moreArrays.c0.bc0"), callbacks, false);
|
||||
test.ok(printout == "2312",
|
||||
"moreArrays.c0.bc0 - Did not print to screen correctly, result was " +
|
||||
printout);
|
||||
@@ -100,7 +77,7 @@ exports.testMoreArray = function(test) {
|
||||
|
||||
exports.testStructs = function(test) {
|
||||
printout = "";
|
||||
var result = c0vm.execute(parser.parse("structs.c0.bc0"), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile("structs.c0.bc0"), callbacks, false);
|
||||
test.ok(printout == "potato chip123",
|
||||
"structs.c0.bc0 - Did not print to screen correctly, result was " +
|
||||
printout);
|
||||
@@ -109,14 +86,14 @@ exports.testStructs = function(test) {
|
||||
|
||||
exports.testAbort = function(test) {
|
||||
test.throws(function () {
|
||||
c0vm.execute(parser.parse("abort.c0.bc0"), callbacks, false);
|
||||
c0vm.execute(parser.parseFile("abort.c0.bc0"), callbacks, false);
|
||||
});
|
||||
test.done();
|
||||
}
|
||||
|
||||
exports.testArith = function(test) {
|
||||
printout = "";
|
||||
var result = c0vm.execute(parser.parse("arith.c0.bc0"), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile("arith.c0.bc0"), callbacks, false);
|
||||
test.ok(printout == "-2147483648 2147483647 -375 -2147483648 -9 -1 12 \n-12 12 Modulus testing 11-1 5 1 Testing constants -251 Testing inequalities \ny1 y2 y3 n4 n5 n6 y7 Testing bitwise operators \n992000 1045310 53250 -12083 Testing bit shifting\n-2147483648 7360588088-31-19\n",
|
||||
"arith.c0.bc0 - Did not print to screen correctly, result was " +
|
||||
printout);
|
||||
@@ -127,9 +104,29 @@ exports.testPIAZZA1 = doTest("piazza1.c0.bc0", 18);
|
||||
|
||||
exports.testSTRINGS = function(test) {
|
||||
printout = "";
|
||||
var result = c0vm.execute(parser.parse("strings.c0.bc0"), callbacks, false);
|
||||
var result = c0vm.execute(parser.parseFile("strings.c0.bc0"), callbacks, false);
|
||||
test.ok(printout == "hello there!?",
|
||||
"strings.c0.bc0 - Did not print to screen correctly, result was " +
|
||||
printout);
|
||||
test.done();
|
||||
}
|
||||
|
||||
exports.testBREAKPOINT1 = function(test) {
|
||||
var vm = c0vm.initialize_vm(parser.parseFile("easyMath.c0.bc0"),
|
||||
callbacks, false);
|
||||
vm.set_breakpoint(0, 4);
|
||||
var result = vm.run();
|
||||
test.ok(result === vm,
|
||||
"VM did not stop at breakpoint, instead returned " + result);
|
||||
test.ok(vm.frame.stack[0] == 23 &&
|
||||
vm.frame.stack[1] == 19,
|
||||
"VM stack incorrect");
|
||||
|
||||
test.ok(vm.bytecode_line == 19,
|
||||
"VM reports incorrect line in bytecode: " + vm.bytecode_line);
|
||||
|
||||
result = vm.run();
|
||||
test.ok(result == 1748,
|
||||
"VM did not resume operation correctly, gave result " + result);
|
||||
test.done();
|
||||
}
|
||||
|
||||
@@ -47,15 +47,14 @@ block script
|
||||
|
||||
function compile() {
|
||||
var code = encodeURIComponent($("#inputCode").val());
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
async: true,
|
||||
url: "http://www.contrib.andrew.cmu.edu/~amgutier/cc0.cgi",
|
||||
dataType: "jsonp",
|
||||
dataType: "json",
|
||||
data: {
|
||||
data: code
|
||||
},
|
||||
jsonpCallback: "callback"
|
||||
success: callback
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user