Merge branch 'run_vm'
Adds basic support for running c0 in browser
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border-color: #ddd;
|
border-color: #ddd;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brad {
|
.brad {
|
||||||
@@ -29,4 +31,5 @@ nav {
|
|||||||
|
|
||||||
.btm-btn {
|
.btm-btn {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
margin-top: -14px;
|
||||||
}
|
}
|
||||||
|
|||||||
4
public/vm/Makefile
Normal file
4
public/vm/Makefile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FILES = c0vm.js bytecode-parser.js byte-stream.js opcodes.js index.js
|
||||||
|
|
||||||
|
all: $(FILES)
|
||||||
|
browserify $(FILES) -o vm.js
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
var ByteStream = function (byte_array) {
|
var ByteStream = function (byte_array) {
|
||||||
console.log("Instance created.");
|
|
||||||
this.byte_array = byte_array;
|
this.byte_array = byte_array;
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
};
|
};
|
||||||
@@ -25,7 +24,7 @@ ByteStream.prototype.get_u4 = function() {
|
|||||||
ByteStream.prototype.get_i4 = function() {
|
ByteStream.prototype.get_i4 = function() {
|
||||||
var unsigned_val = this.get_u4();
|
var unsigned_val = this.get_u4();
|
||||||
var sign_mult = (unsigned_val & 0x80000000) ? -1 : 1;
|
var sign_mult = (unsigned_val & 0x80000000) ? -1 : 1;
|
||||||
return (unsigned_val & 0x7FFFFFFF) * sign_mult;
|
return (unsigned_val & 0x7FFFFFFF) + (unsigned_val & 0x80000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteStream.prototype.get_bytes = function(n) {
|
ByteStream.prototype.get_bytes = function(n) {
|
||||||
@@ -2,7 +2,9 @@ fs = require("fs");
|
|||||||
byte_stream = require("./byte-stream");
|
byte_stream = require("./byte-stream");
|
||||||
|
|
||||||
// This is a simple, kinda hacky bytecode parser for .bc0 files
|
// 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);
|
var data = fs.readFileSync(filename);
|
||||||
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
@@ -12,9 +14,11 @@ function getBytes(filename) {
|
|||||||
console.log("Error: " + err);
|
console.log("Error: " + err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Data contains our file, but we want it as a string
|
// Data contains our file, but we want it as a string
|
||||||
var string_data = data.toString();
|
var string_data = data.toString();
|
||||||
|
console.log(string_data);
|
||||||
|
|
||||||
// Strip all the comments for easier parsing
|
// Strip all the comments for easier parsing
|
||||||
var without_comments = string_data.replace(new RegExp("#.*", "gi"), "");
|
var without_comments = string_data.replace(new RegExp("#.*", "gi"), "");
|
||||||
@@ -29,6 +33,7 @@ function getBytes(filename) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// We now have an array of bytes. That's probably everything we need, right?
|
// We now have an array of bytes. That's probably everything we need, right?
|
||||||
|
console.log(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -72,10 +77,11 @@ var Bc0File = function (filename) {
|
|||||||
for (var i = 0; i < this.string_count; i++) {
|
for (var i = 0; i < this.string_count; i++) {
|
||||||
var c = stream.get_u1();
|
var c = stream.get_u1();
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
this.string_pool.push(current_string);
|
// this.string_pool.push(current_string);
|
||||||
current_string = "";
|
// current_string = "";
|
||||||
|
this.string_pool.push(0);
|
||||||
} else {
|
} else {
|
||||||
current_string += String.fromCharCode(c);
|
this.string_pool.push(String.fromCharCode(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +99,15 @@ var Bc0File = function (filename) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bc0File.prototype.string_from_index = function (i) {
|
||||||
|
var result = "";
|
||||||
|
while (this.string_pool[i] !== 0 && i < this.string_pool.length) {
|
||||||
|
result += this.string_pool[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function parse(filename) {
|
function parse(filename) {
|
||||||
return new Bc0File(filename);
|
return new Bc0File(filename);
|
||||||
}
|
}
|
||||||
110
public/vm/c0ffi.js
Normal file
110
public/vm/c0ffi.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
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
|
||||||
|
|
||||||
506
public/vm/c0vm.js
Executable file
506
public/vm/c0vm.js
Executable file
@@ -0,0 +1,506 @@
|
|||||||
|
op = require("./opcodes");
|
||||||
|
|
||||||
|
var INT_MIN = 0x80000000;
|
||||||
|
var INT_MAX = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
var verbose = false;
|
||||||
|
function log(message) {
|
||||||
|
if (verbose) console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function c0_assertion_failure(val) {
|
||||||
|
throw ("c0 assertion failure: " + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function c0_memory_error(val) {
|
||||||
|
throw ("c0 memory error: " + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function num_to_i32(num) {
|
||||||
|
log("num is 0x" + num.toString(16));
|
||||||
|
log("num & 0x7FFFFFFF is " + (num & 0x7FFFFFFF));
|
||||||
|
log("neg factor is " + ( (num & 0x80000000)));
|
||||||
|
return (num & 0x7FFFFFFF) + ((num & 0x80000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
function i32_to_array(i32) {
|
||||||
|
return [(i32 & 0xFF),
|
||||||
|
((i32 >> 8) & 0xFF),
|
||||||
|
((i32 >> 16) & 0xFF),
|
||||||
|
((i32 >> 24) & 0xFF)];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function array_to_i32(array) {
|
||||||
|
return array[0] +
|
||||||
|
(array[1] << 8) +
|
||||||
|
(array[2] << 16) +
|
||||||
|
(array[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
var StackFrame = function(file, f) {
|
||||||
|
log("Creating stack frame");
|
||||||
|
this.stack = [];
|
||||||
|
this.pc = 0;
|
||||||
|
this.program = f.code;
|
||||||
|
this.variables = [];
|
||||||
|
for (var i = 0; i < f.num_vars; i++)
|
||||||
|
this.variables.push(0);
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ProgramState = function(parsed_file, callback_dict) {
|
||||||
|
log("Creating program state with file " + parsed_file);
|
||||||
|
var main_function = parsed_file.function_pool[0];
|
||||||
|
|
||||||
|
this.frame = new StackFrame(parsed_file, parsed_file.function_pool[0]);
|
||||||
|
this.call_stack = [];
|
||||||
|
this.file = parsed_file;
|
||||||
|
|
||||||
|
this.natives = {};
|
||||||
|
|
||||||
|
for (var i = 0; i < 95; i++) {
|
||||||
|
try {
|
||||||
|
this.natives[i] = callback_dict[i];
|
||||||
|
} catch (key_not_found) {
|
||||||
|
this.natives[i] = function (arg) {
|
||||||
|
console.log("Native function " + name + " called, ran method stub.");
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Structs are stored as themselves
|
||||||
|
// Arrays are stored as an entry for the number of elements
|
||||||
|
// and then the array, byte-by-byte
|
||||||
|
this.heap = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.push = function(val) {
|
||||||
|
this.frame.stack.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.pop = function() {
|
||||||
|
if (this.frame.stack === [])
|
||||||
|
throw "Tried to pop from an empty stack!";
|
||||||
|
return this.frame.stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.goto_offset = function() {
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2]
|
||||||
|
|
||||||
|
var address_offset = (c1 << 8) + c2;
|
||||||
|
// Handle negative values
|
||||||
|
if ((address_offset & 0x8000) != 0)
|
||||||
|
address_offset = -0x8000 + (address_offset & 0x7FFF);
|
||||||
|
|
||||||
|
this.frame.pc += address_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.doIf = function(f) {
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (f(x,y)) {
|
||||||
|
this.goto_offset();
|
||||||
|
} else {
|
||||||
|
this.frame.pc += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.step = function() {
|
||||||
|
var opcode = this.frame.program[this.frame.pc]
|
||||||
|
log("0x" + this.frame.pc.toString(16) + " Running opcode " +
|
||||||
|
op.lookup_table[opcode]);
|
||||||
|
switch (opcode) {
|
||||||
|
// Stack manipulation
|
||||||
|
case op.POP:
|
||||||
|
this.frame.pc++;
|
||||||
|
this.pop();
|
||||||
|
break;
|
||||||
|
case op.DUP:
|
||||||
|
this.frame.pc++;
|
||||||
|
var v = this.pop();
|
||||||
|
this.push(v);
|
||||||
|
this.push(v);
|
||||||
|
break;
|
||||||
|
case op.SWAP:
|
||||||
|
this.frame.pc++;
|
||||||
|
var v1 = this.pop();
|
||||||
|
var v2 = this.pop();
|
||||||
|
this.push(v1);
|
||||||
|
this.push(v2);
|
||||||
|
break;
|
||||||
|
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);
|
||||||
|
this.push(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Returning from a function
|
||||||
|
case op.RETURN:
|
||||||
|
var retVal = this.pop();
|
||||||
|
if (this.call_stack.length == 0)
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
this.frame = this.call_stack.pop();
|
||||||
|
this.push(retVal);
|
||||||
|
|
||||||
|
break;
|
||||||
|
// Arithmetic
|
||||||
|
case op.IADD:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
log("Adding " + x + " and " + y);
|
||||||
|
this.push(num_to_i32(x+y));
|
||||||
|
break;
|
||||||
|
case op.ISUB:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
log("Subtracting " + x + " and " + y);
|
||||||
|
this.push(num_to_i32(x-y));
|
||||||
|
break;
|
||||||
|
case op.IMUL:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(num_to_i32(x*y));
|
||||||
|
break;
|
||||||
|
case op.IDIV:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y == 0) c0_arith_error("Divide by zero");
|
||||||
|
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
||||||
|
|
||||||
|
// This does int division.
|
||||||
|
// As I understand it, the ~~ is treated as the identity on integers
|
||||||
|
// which forces the type to int, not float
|
||||||
|
this.push(~~(x/y));
|
||||||
|
break;
|
||||||
|
case op.IREM:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y == 0) c0_arith_error("Divide by zero");
|
||||||
|
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
||||||
|
this.push(x%y);
|
||||||
|
break;
|
||||||
|
case op.IAND:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x&y);
|
||||||
|
break;
|
||||||
|
case op.IOR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x|y);
|
||||||
|
break;
|
||||||
|
case op.IXOR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x^y);
|
||||||
|
break;
|
||||||
|
case op.ISHL:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
|
||||||
|
this.push(x<<y);
|
||||||
|
break;
|
||||||
|
case op.ISHR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
|
||||||
|
this.push(x>>y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Operations on local variables
|
||||||
|
|
||||||
|
case op.VLOAD:
|
||||||
|
this.frame.pc += 2;
|
||||||
|
var index = this.frame.program[this.frame.pc-1];
|
||||||
|
this.push(this.frame.variables[index]);
|
||||||
|
break;
|
||||||
|
case op.VSTORE:
|
||||||
|
this.frame.pc += 2;
|
||||||
|
var index = this.frame.program[this.frame.pc-1];
|
||||||
|
var val = this.pop();
|
||||||
|
this.frame.variables[index] = val;
|
||||||
|
log("Set variable " + index + " to value " + val);
|
||||||
|
break;
|
||||||
|
case op.ACONST_NULL:
|
||||||
|
this.frame.pc++;
|
||||||
|
this.push(0);
|
||||||
|
break;
|
||||||
|
case op.ILDC:
|
||||||
|
this.frame.pc += 3;
|
||||||
|
var c1 = this.frame.program[this.frame.pc-2];
|
||||||
|
var c2 = this.frame.program[this.frame.pc-1];
|
||||||
|
var index = (c1 * 0x1000) + c2;
|
||||||
|
|
||||||
|
this.push(this.file.int_pool[index]);
|
||||||
|
break;
|
||||||
|
case op.ALDC:
|
||||||
|
this.frame.pc += 3;
|
||||||
|
var c1 = this.frame.program[this.frame.pc-2];
|
||||||
|
var c2 = this.frame.program[this.frame.pc-1];
|
||||||
|
var index = (c1 * 0x1000) + c2;
|
||||||
|
|
||||||
|
this.push(this.file.string_from_index(index));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Control flow
|
||||||
|
case op.NOP:
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
case op.IF_CMPEQ:
|
||||||
|
this.doIf(function (x,y) {return y == x;});
|
||||||
|
break;
|
||||||
|
case op.IF_CMPNE:
|
||||||
|
this.doIf(function (x,y) {return y != x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPLT:
|
||||||
|
this.doIf(function (x,y) {return y > x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPGE:
|
||||||
|
this.doIf(function (x,y) {return y <= x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPGT:
|
||||||
|
this.doIf(function (x,y) {return y < x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPLE:
|
||||||
|
this.doIf(function (x,y) {return y >= x;});
|
||||||
|
break;
|
||||||
|
case op.GOTO:
|
||||||
|
this.goto_offset();
|
||||||
|
break;
|
||||||
|
case op.ATHROW:
|
||||||
|
this.frame.pc++;
|
||||||
|
c0_user_error(this.pop());
|
||||||
|
break;
|
||||||
|
case op.ASSERT:
|
||||||
|
this.frame.pc++;
|
||||||
|
var a = this.pop();
|
||||||
|
if (this.pop() == 0)
|
||||||
|
c0_assertion_failure(a);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Function call operations
|
||||||
|
|
||||||
|
case op.INVOKESTATIC:
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2];
|
||||||
|
this.frame.pc += 3;
|
||||||
|
|
||||||
|
var index = (c1 << 8) + c2;
|
||||||
|
|
||||||
|
var f = this.file.function_pool[index];
|
||||||
|
var newFrame = new StackFrame(this.file, f);
|
||||||
|
for (var i = f.num_args - 1; i >= 0; i--) {
|
||||||
|
newFrame.variables[i] = this.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.call_stack.push(this.frame);
|
||||||
|
this.frame = newFrame;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.INVOKENATIVE:
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2];
|
||||||
|
this.frame.pc += 3;
|
||||||
|
|
||||||
|
var index = (c1 << 8) + c2;
|
||||||
|
|
||||||
|
var f = this.file.native_pool[index];
|
||||||
|
var arg_array = [];
|
||||||
|
for (var i = f.num_args - 1; i >= 0; i--)
|
||||||
|
arg_array[i] = this.pop();
|
||||||
|
|
||||||
|
var native_function = this.natives[f.function_table_index];
|
||||||
|
if (native_function === undefined) {
|
||||||
|
native_function = function (ignored) {
|
||||||
|
console.log("Could not find native function with index " +
|
||||||
|
f.function_table_index);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
console.log("Unknown native function index " + f.function_table_index);
|
||||||
|
}
|
||||||
|
log("Calling native function with index " + index + " with arguments " +
|
||||||
|
arg_array);
|
||||||
|
this.push(native_function(arg_array));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Memory allocation operations:
|
||||||
|
|
||||||
|
case op.NEW:
|
||||||
|
var size = this.frame.program[this.frame.pc+1];
|
||||||
|
var address = this.heap.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < size; i++) this.heap.push(0);
|
||||||
|
|
||||||
|
this.push(address);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.NEWARRAY:
|
||||||
|
var size = this.frame.program[this.frame.pc+1];
|
||||||
|
var address = this.heap.length;
|
||||||
|
var num_elements = this.pop();
|
||||||
|
if (num_elements < 0) c0_memory_error("Array size must be nonnegative");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.push(address);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.ARRAYLENGTH:
|
||||||
|
var pointer = this.pop();
|
||||||
|
this.push(this.heap[pointer]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Memory access operations:
|
||||||
|
|
||||||
|
case op.AADDF:
|
||||||
|
// Read offset into a struct
|
||||||
|
var offset = this.frame.program[this.frame.pc + 1];
|
||||||
|
var index = this.pop();
|
||||||
|
this.push(index + offset);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AADDS:
|
||||||
|
// Read offset into an array
|
||||||
|
var elt_index = this.pop();
|
||||||
|
var index = this.pop();
|
||||||
|
|
||||||
|
if (typeof index == "string") {
|
||||||
|
this.push(index.slice(elt_index));
|
||||||
|
} else {
|
||||||
|
var array_length = this.heap[index];
|
||||||
|
var elt_size = this.heap[index+1];
|
||||||
|
if (elt_index >= array_length)
|
||||||
|
c0_memory_error("Array index out of bounds.");
|
||||||
|
this.push(index + 2 + (elt_size*elt_index));
|
||||||
|
}
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.IMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
// Get int32 from bytes
|
||||||
|
var c1 = this.heap[addr];
|
||||||
|
var c2 = this.heap[addr+1];
|
||||||
|
var c3 = this.heap[addr+2];
|
||||||
|
var c4 = this.heap[addr+3];
|
||||||
|
var combined = array_to_i32([c1, c2, c3, c4]);
|
||||||
|
this.push(combined);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.IMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
var array = i32_to_array(value);
|
||||||
|
|
||||||
|
for (var i = 0; i < 4; i++)
|
||||||
|
this.heap[addr + i] = array[i];
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
this.push(this.heap[addr]);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
this.heap[addr] = value;
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.CMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
if (typeof addr == "string")
|
||||||
|
this.push(addr);
|
||||||
|
else
|
||||||
|
this.push(this.heap[addr]);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.CMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
this.heap[addr] = value;
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var opcode_name;
|
||||||
|
try {
|
||||||
|
opcode_name = op.lookup_table[opcode];
|
||||||
|
} catch (ignored) {
|
||||||
|
opcode_name = "UNKNOWN";
|
||||||
|
}
|
||||||
|
console.log("Error: Unknown opcode: 0x" + opcode.toString(16) +
|
||||||
|
" (" + opcode_name + ")\n");
|
||||||
|
throw "Error - unknown opcode";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes in a parsed .bc0 file and runs it
|
||||||
|
function execute(file, callbacks, v) {
|
||||||
|
verbose = typeof v !== 'undefined' ? v : true;
|
||||||
|
log("Initializing with file " + file);
|
||||||
|
|
||||||
|
var state = new ProgramState(file, callbacks);
|
||||||
|
|
||||||
|
if (verbose) log(file);
|
||||||
|
|
||||||
|
log("Beginning execution");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var val = state.step();
|
||||||
|
if (val !== undefined) return val;
|
||||||
|
|
||||||
|
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;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.execute = execute;
|
||||||
39
public/vm/index.js
Normal file
39
public/vm/index.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
parser = require("./bytecode-parser");
|
||||||
|
c0vm = require("./c0vm.js");
|
||||||
|
c0ffi = require("./c0ffi.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);
|
||||||
|
|
||||||
|
// UI interaction functions
|
||||||
|
|
||||||
|
function print(arg) {
|
||||||
|
$("#output").append(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks = {};
|
||||||
|
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||||
|
print(args[0]);
|
||||||
|
print("<br />");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks[c0ffi.NATIVE_PRINTINT] = function(args) {
|
||||||
|
print(args[0]);
|
||||||
|
print("<br />");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(callbacks);
|
||||||
|
|
||||||
|
$("#run").click(function() {
|
||||||
|
var input = $("#bytecode").html().replace(/(\r\n|\n|\r)/gm,"");
|
||||||
|
var file = parser.parse($("#bytecode").text());
|
||||||
|
print("<br />");
|
||||||
|
print(c0vm.execute(file, callbacks));
|
||||||
|
});
|
||||||
@@ -90,12 +90,12 @@ exports.lookup_table = {
|
|||||||
0x13: "ILDC",
|
0x13: "ILDC",
|
||||||
0x14: "ALDC",
|
0x14: "ALDC",
|
||||||
0x00: "NOP",
|
0x00: "NOP",
|
||||||
0x9F: "IF",
|
0x9F: "IF_CMPEQ",
|
||||||
0xA0: "IF",
|
0xA0: "IF_CMPNE",
|
||||||
0xA1: "IF",
|
0xA1: "IF_ICMPLT",
|
||||||
0xA2: "IF",
|
0xA2: "IF_ICMPGE",
|
||||||
0xA3: "IF",
|
0xA3: "IF_ICMPGT",
|
||||||
0xA4: "IF",
|
0xA4: "IF_ICMPLE",
|
||||||
0xA7: "GOTO",
|
0xA7: "GOTO",
|
||||||
0xBF: "ATHROW",
|
0xBF: "ATHROW",
|
||||||
0xCF: "ASSERT",
|
0xCF: "ASSERT",
|
||||||
929
public/vm/vm.js
Normal file
929
public/vm/vm.js
Normal file
@@ -0,0 +1,929 @@
|
|||||||
|
(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<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
var ByteStream = function (byte_array) {
|
||||||
|
this.byte_array = byte_array;
|
||||||
|
this.index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ByteStream.prototype.get_u1 = function() {
|
||||||
|
var result = this.byte_array[this.index];
|
||||||
|
this.index += 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteStream.prototype.get_u2 = function() {
|
||||||
|
var high = this.get_u1();
|
||||||
|
var low = this.get_u1();
|
||||||
|
return (high << 8) + low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteStream.prototype.get_u4 = function() {
|
||||||
|
var high = this.get_u2();
|
||||||
|
var low = this.get_u2();
|
||||||
|
return (high * 0x10000) + low;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteStream.prototype.get_i4 = function() {
|
||||||
|
var unsigned_val = this.get_u4();
|
||||||
|
var sign_mult = (unsigned_val & 0x80000000) ? -1 : 1;
|
||||||
|
return (unsigned_val & 0x7FFFFFFF) + (unsigned_val & 0x80000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteStream.prototype.get_bytes = function(n) {
|
||||||
|
var result = [];
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
result.push(this.get_u1());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.ByteStream = ByteStream;
|
||||||
|
|
||||||
|
},{}],2:[function(require,module,exports){
|
||||||
|
fs = require("fs");
|
||||||
|
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"), "");
|
||||||
|
|
||||||
|
// Each byte should now be a pair of two hex digits.
|
||||||
|
// Put all these in an array.
|
||||||
|
var bytes = [];
|
||||||
|
without_comments.replace(
|
||||||
|
new RegExp("([0123456789ABCDEF][0123456789ABCDEF])", "gi"),
|
||||||
|
function(next_byte) {
|
||||||
|
bytes.push(parseInt(next_byte, 16));
|
||||||
|
});
|
||||||
|
|
||||||
|
// We now have an array of bytes. That's probably everything we need, right?
|
||||||
|
console.log(bytes);
|
||||||
|
return bytes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var FunctionInfo = function (stream) {
|
||||||
|
this.num_args = stream.get_u2();
|
||||||
|
this.num_vars = stream.get_u2();
|
||||||
|
this.code_length = stream.get_u2();
|
||||||
|
this.code = stream.get_bytes(this.code_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
var NativeInfo = function (stream) {
|
||||||
|
this.num_args = stream.get_u2();
|
||||||
|
this.function_table_index = stream.get_u2();
|
||||||
|
}
|
||||||
|
|
||||||
|
var Bc0File = function (filename) {
|
||||||
|
var file = getBytes(filename);
|
||||||
|
var stream = new byte_stream.ByteStream(file);
|
||||||
|
|
||||||
|
var magic = stream.get_u4();
|
||||||
|
if (magic != 0xc0c0ffee) {
|
||||||
|
console.log("Error - file is not a c0 bytecode file");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// I don't know that we need this, but here it is
|
||||||
|
this.version_arch = stream.get_u2();
|
||||||
|
|
||||||
|
this.int_count = stream.get_u2();
|
||||||
|
|
||||||
|
this.int_pool = [];
|
||||||
|
for (var i = 0; i < this.int_count; i++) {
|
||||||
|
this.int_pool[i] = stream.get_i4();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.string_count = stream.get_u2();
|
||||||
|
|
||||||
|
this.string_pool = [];
|
||||||
|
var current_string = "";
|
||||||
|
for (var i = 0; i < this.string_count; i++) {
|
||||||
|
var c = stream.get_u1();
|
||||||
|
if (c == 0) {
|
||||||
|
// this.string_pool.push(current_string);
|
||||||
|
// current_string = "";
|
||||||
|
this.string_pool.push(0);
|
||||||
|
} else {
|
||||||
|
this.string_pool.push(String.fromCharCode(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.function_count = stream.get_u2();
|
||||||
|
|
||||||
|
this.function_pool = [];
|
||||||
|
for (var i = 0; i < this.function_count; i++) {
|
||||||
|
this.function_pool.push(new FunctionInfo(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.native_count = stream.get_u2();
|
||||||
|
this.native_pool = [];
|
||||||
|
for (var i = 0; i < this.native_count; i++) {
|
||||||
|
this.native_pool.push(new NativeInfo(stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bc0File.prototype.string_from_index = function (i) {
|
||||||
|
var result = "";
|
||||||
|
while (this.string_pool[i] !== 0 && i < this.string_pool.length) {
|
||||||
|
result += this.string_pool[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(filename) {
|
||||||
|
return new Bc0File(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getBytes = getBytes;
|
||||||
|
exports.parse = parse;
|
||||||
|
|
||||||
|
},{"./byte-stream":1,"fs":7}],3:[function(require,module,exports){
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
},{}],4:[function(require,module,exports){
|
||||||
|
op = require("./opcodes");
|
||||||
|
|
||||||
|
var INT_MIN = 0x80000000;
|
||||||
|
var INT_MAX = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
var verbose = false;
|
||||||
|
function log(message) {
|
||||||
|
if (verbose) console.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function c0_assertion_failure(val) {
|
||||||
|
throw ("c0 assertion failure: " + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function c0_memory_error(val) {
|
||||||
|
throw ("c0 memory error: " + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function num_to_i32(num) {
|
||||||
|
log("num is 0x" + num.toString(16));
|
||||||
|
log("num & 0x7FFFFFFF is " + (num & 0x7FFFFFFF));
|
||||||
|
log("neg factor is " + ( (num & 0x80000000)));
|
||||||
|
return (num & 0x7FFFFFFF) + ((num & 0x80000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
function i32_to_array(i32) {
|
||||||
|
return [(i32 & 0xFF),
|
||||||
|
((i32 >> 8) & 0xFF),
|
||||||
|
((i32 >> 16) & 0xFF),
|
||||||
|
((i32 >> 24) & 0xFF)];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function array_to_i32(array) {
|
||||||
|
return array[0] +
|
||||||
|
(array[1] << 8) +
|
||||||
|
(array[2] << 16) +
|
||||||
|
(array[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
var StackFrame = function(file, f) {
|
||||||
|
log("Creating stack frame");
|
||||||
|
this.stack = [];
|
||||||
|
this.pc = 0;
|
||||||
|
this.program = f.code;
|
||||||
|
this.variables = [];
|
||||||
|
for (var i = 0; i < f.num_vars; i++)
|
||||||
|
this.variables.push(0);
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ProgramState = function(parsed_file, callback_dict) {
|
||||||
|
log("Creating program state with file " + parsed_file);
|
||||||
|
var main_function = parsed_file.function_pool[0];
|
||||||
|
|
||||||
|
this.frame = new StackFrame(parsed_file, parsed_file.function_pool[0]);
|
||||||
|
this.call_stack = [];
|
||||||
|
this.file = parsed_file;
|
||||||
|
|
||||||
|
this.natives = {};
|
||||||
|
|
||||||
|
for (var i = 0; i < 95; i++) {
|
||||||
|
try {
|
||||||
|
this.natives[i] = callback_dict[i];
|
||||||
|
} catch (key_not_found) {
|
||||||
|
this.natives[i] = function (arg) {
|
||||||
|
console.log("Native function " + name + " called, ran method stub.");
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Structs are stored as themselves
|
||||||
|
// Arrays are stored as an entry for the number of elements
|
||||||
|
// and then the array, byte-by-byte
|
||||||
|
this.heap = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.push = function(val) {
|
||||||
|
this.frame.stack.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.pop = function() {
|
||||||
|
if (this.frame.stack === [])
|
||||||
|
throw "Tried to pop from an empty stack!";
|
||||||
|
return this.frame.stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.goto_offset = function() {
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2]
|
||||||
|
|
||||||
|
var address_offset = (c1 << 8) + c2;
|
||||||
|
// Handle negative values
|
||||||
|
if ((address_offset & 0x8000) != 0)
|
||||||
|
address_offset = -0x8000 + (address_offset & 0x7FFF);
|
||||||
|
|
||||||
|
this.frame.pc += address_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.doIf = function(f) {
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (f(x,y)) {
|
||||||
|
this.goto_offset();
|
||||||
|
} else {
|
||||||
|
this.frame.pc += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramState.prototype.step = function() {
|
||||||
|
var opcode = this.frame.program[this.frame.pc]
|
||||||
|
log("0x" + this.frame.pc.toString(16) + " Running opcode " +
|
||||||
|
op.lookup_table[opcode]);
|
||||||
|
switch (opcode) {
|
||||||
|
// Stack manipulation
|
||||||
|
case op.POP:
|
||||||
|
this.frame.pc++;
|
||||||
|
this.pop();
|
||||||
|
break;
|
||||||
|
case op.DUP:
|
||||||
|
this.frame.pc++;
|
||||||
|
var v = this.pop();
|
||||||
|
this.push(v);
|
||||||
|
this.push(v);
|
||||||
|
break;
|
||||||
|
case op.SWAP:
|
||||||
|
this.frame.pc++;
|
||||||
|
var v1 = this.pop();
|
||||||
|
var v2 = this.pop();
|
||||||
|
this.push(v1);
|
||||||
|
this.push(v2);
|
||||||
|
break;
|
||||||
|
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);
|
||||||
|
this.push(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Returning from a function
|
||||||
|
case op.RETURN:
|
||||||
|
var retVal = this.pop();
|
||||||
|
if (this.call_stack.length == 0)
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
this.frame = this.call_stack.pop();
|
||||||
|
this.push(retVal);
|
||||||
|
|
||||||
|
break;
|
||||||
|
// Arithmetic
|
||||||
|
case op.IADD:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
log("Adding " + x + " and " + y);
|
||||||
|
this.push(num_to_i32(x+y));
|
||||||
|
break;
|
||||||
|
case op.ISUB:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
log("Subtracting " + x + " and " + y);
|
||||||
|
this.push(num_to_i32(x-y));
|
||||||
|
break;
|
||||||
|
case op.IMUL:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(num_to_i32(x*y));
|
||||||
|
break;
|
||||||
|
case op.IDIV:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y == 0) c0_arith_error("Divide by zero");
|
||||||
|
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
||||||
|
|
||||||
|
// This does int division.
|
||||||
|
// As I understand it, the ~~ is treated as the identity on integers
|
||||||
|
// which forces the type to int, not float
|
||||||
|
this.push(~~(x/y));
|
||||||
|
break;
|
||||||
|
case op.IREM:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y == 0) c0_arith_error("Divide by zero");
|
||||||
|
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
||||||
|
this.push(x%y);
|
||||||
|
break;
|
||||||
|
case op.IAND:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x&y);
|
||||||
|
break;
|
||||||
|
case op.IOR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x|y);
|
||||||
|
break;
|
||||||
|
case op.IXOR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
this.push(x^y);
|
||||||
|
break;
|
||||||
|
case op.ISHL:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
|
||||||
|
this.push(x<<y);
|
||||||
|
break;
|
||||||
|
case op.ISHR:
|
||||||
|
this.frame.pc++;
|
||||||
|
var y = this.pop();
|
||||||
|
var x = this.pop();
|
||||||
|
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
|
||||||
|
this.push(x>>y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Operations on local variables
|
||||||
|
|
||||||
|
case op.VLOAD:
|
||||||
|
this.frame.pc += 2;
|
||||||
|
var index = this.frame.program[this.frame.pc-1];
|
||||||
|
this.push(this.frame.variables[index]);
|
||||||
|
break;
|
||||||
|
case op.VSTORE:
|
||||||
|
this.frame.pc += 2;
|
||||||
|
var index = this.frame.program[this.frame.pc-1];
|
||||||
|
var val = this.pop();
|
||||||
|
this.frame.variables[index] = val;
|
||||||
|
log("Set variable " + index + " to value " + val);
|
||||||
|
break;
|
||||||
|
case op.ACONST_NULL:
|
||||||
|
this.frame.pc++;
|
||||||
|
this.push(0);
|
||||||
|
break;
|
||||||
|
case op.ILDC:
|
||||||
|
this.frame.pc += 3;
|
||||||
|
var c1 = this.frame.program[this.frame.pc-2];
|
||||||
|
var c2 = this.frame.program[this.frame.pc-1];
|
||||||
|
var index = (c1 * 0x1000) + c2;
|
||||||
|
|
||||||
|
this.push(this.file.int_pool[index]);
|
||||||
|
break;
|
||||||
|
case op.ALDC:
|
||||||
|
this.frame.pc += 3;
|
||||||
|
var c1 = this.frame.program[this.frame.pc-2];
|
||||||
|
var c2 = this.frame.program[this.frame.pc-1];
|
||||||
|
var index = (c1 * 0x1000) + c2;
|
||||||
|
|
||||||
|
this.push(this.file.string_from_index(index));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Control flow
|
||||||
|
case op.NOP:
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
case op.IF_CMPEQ:
|
||||||
|
this.doIf(function (x,y) {return y == x;});
|
||||||
|
break;
|
||||||
|
case op.IF_CMPNE:
|
||||||
|
this.doIf(function (x,y) {return y != x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPLT:
|
||||||
|
this.doIf(function (x,y) {return y > x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPGE:
|
||||||
|
this.doIf(function (x,y) {return y <= x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPGT:
|
||||||
|
this.doIf(function (x,y) {return y < x;});
|
||||||
|
break;
|
||||||
|
case op.IF_ICMPLE:
|
||||||
|
this.doIf(function (x,y) {return y >= x;});
|
||||||
|
break;
|
||||||
|
case op.GOTO:
|
||||||
|
this.goto_offset();
|
||||||
|
break;
|
||||||
|
case op.ATHROW:
|
||||||
|
this.frame.pc++;
|
||||||
|
c0_user_error(this.pop());
|
||||||
|
break;
|
||||||
|
case op.ASSERT:
|
||||||
|
this.frame.pc++;
|
||||||
|
var a = this.pop();
|
||||||
|
if (this.pop() == 0)
|
||||||
|
c0_assertion_failure(a);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Function call operations
|
||||||
|
|
||||||
|
case op.INVOKESTATIC:
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2];
|
||||||
|
this.frame.pc += 3;
|
||||||
|
|
||||||
|
var index = (c1 << 8) + c2;
|
||||||
|
|
||||||
|
var f = this.file.function_pool[index];
|
||||||
|
var newFrame = new StackFrame(this.file, f);
|
||||||
|
for (var i = f.num_args - 1; i >= 0; i--) {
|
||||||
|
newFrame.variables[i] = this.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.call_stack.push(this.frame);
|
||||||
|
this.frame = newFrame;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.INVOKENATIVE:
|
||||||
|
var c1 = this.frame.program[this.frame.pc+1];
|
||||||
|
var c2 = this.frame.program[this.frame.pc+2];
|
||||||
|
this.frame.pc += 3;
|
||||||
|
|
||||||
|
var index = (c1 << 8) + c2;
|
||||||
|
|
||||||
|
var f = this.file.native_pool[index];
|
||||||
|
var arg_array = [];
|
||||||
|
for (var i = f.num_args - 1; i >= 0; i--)
|
||||||
|
arg_array[i] = this.pop();
|
||||||
|
|
||||||
|
var native_function = this.natives[f.function_table_index];
|
||||||
|
if (native_function === undefined) {
|
||||||
|
native_function = function (ignored) {
|
||||||
|
console.log("Could not find native function with index " +
|
||||||
|
f.function_table_index);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
console.log("Unknown native function index " + f.function_table_index);
|
||||||
|
}
|
||||||
|
log("Calling native function with index " + index + " with arguments " +
|
||||||
|
arg_array);
|
||||||
|
this.push(native_function(arg_array));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Memory allocation operations:
|
||||||
|
|
||||||
|
case op.NEW:
|
||||||
|
var size = this.frame.program[this.frame.pc+1];
|
||||||
|
var address = this.heap.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < size; i++) this.heap.push(0);
|
||||||
|
|
||||||
|
this.push(address);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.NEWARRAY:
|
||||||
|
var size = this.frame.program[this.frame.pc+1];
|
||||||
|
var address = this.heap.length;
|
||||||
|
var num_elements = this.pop();
|
||||||
|
if (num_elements < 0) c0_memory_error("Array size must be nonnegative");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.push(address);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.ARRAYLENGTH:
|
||||||
|
var pointer = this.pop();
|
||||||
|
this.push(this.heap[pointer]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Memory access operations:
|
||||||
|
|
||||||
|
case op.AADDF:
|
||||||
|
// Read offset into a struct
|
||||||
|
var offset = this.frame.program[this.frame.pc + 1];
|
||||||
|
var index = this.pop();
|
||||||
|
this.push(index + offset);
|
||||||
|
this.frame.pc += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AADDS:
|
||||||
|
// Read offset into an array
|
||||||
|
var elt_index = this.pop();
|
||||||
|
var index = this.pop();
|
||||||
|
|
||||||
|
if (typeof index == "string") {
|
||||||
|
this.push(index.slice(elt_index));
|
||||||
|
} else {
|
||||||
|
var array_length = this.heap[index];
|
||||||
|
var elt_size = this.heap[index+1];
|
||||||
|
if (elt_index >= array_length)
|
||||||
|
c0_memory_error("Array index out of bounds.");
|
||||||
|
this.push(index + 2 + (elt_size*elt_index));
|
||||||
|
}
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.IMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
// Get int32 from bytes
|
||||||
|
var c1 = this.heap[addr];
|
||||||
|
var c2 = this.heap[addr+1];
|
||||||
|
var c3 = this.heap[addr+2];
|
||||||
|
var c4 = this.heap[addr+3];
|
||||||
|
var combined = array_to_i32([c1, c2, c3, c4]);
|
||||||
|
this.push(combined);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.IMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
var array = i32_to_array(value);
|
||||||
|
|
||||||
|
for (var i = 0; i < 4; i++)
|
||||||
|
this.heap[addr + i] = array[i];
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
this.push(this.heap[addr]);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.AMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
this.heap[addr] = value;
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.CMLOAD:
|
||||||
|
var addr = this.pop();
|
||||||
|
if (typeof addr == "string")
|
||||||
|
this.push(addr);
|
||||||
|
else
|
||||||
|
this.push(this.heap[addr]);
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case op.CMSTORE:
|
||||||
|
var value = this.pop();
|
||||||
|
var addr = this.pop();
|
||||||
|
this.heap[addr] = value;
|
||||||
|
this.frame.pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
var opcode_name;
|
||||||
|
try {
|
||||||
|
opcode_name = op.lookup_table[opcode];
|
||||||
|
} catch (ignored) {
|
||||||
|
opcode_name = "UNKNOWN";
|
||||||
|
}
|
||||||
|
console.log("Error: Unknown opcode: 0x" + opcode.toString(16) +
|
||||||
|
" (" + opcode_name + ")\n");
|
||||||
|
throw "Error - unknown opcode";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes in a parsed .bc0 file and runs it
|
||||||
|
function execute(file, callbacks, v) {
|
||||||
|
verbose = typeof v !== 'undefined' ? v : true;
|
||||||
|
log("Initializing with file " + file);
|
||||||
|
|
||||||
|
var state = new ProgramState(file, callbacks);
|
||||||
|
|
||||||
|
if (verbose) log(file);
|
||||||
|
|
||||||
|
log("Beginning execution");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var val = state.step();
|
||||||
|
if (val !== undefined) return val;
|
||||||
|
|
||||||
|
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;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.execute = execute;
|
||||||
|
|
||||||
|
},{"./opcodes":6}],5:[function(require,module,exports){
|
||||||
|
parser = require("./bytecode-parser");
|
||||||
|
c0vm = require("./c0vm.js");
|
||||||
|
c0ffi = require("./c0ffi.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);
|
||||||
|
|
||||||
|
// UI interaction functions
|
||||||
|
|
||||||
|
function print(arg) {
|
||||||
|
$("#output").append(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks = {};
|
||||||
|
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||||
|
print(args[0]);
|
||||||
|
print("<br />");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks[c0ffi.NATIVE_PRINTINT] = function(args) {
|
||||||
|
print(args[0]);
|
||||||
|
print("<br />");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(callbacks);
|
||||||
|
|
||||||
|
$("#run").click(function() {
|
||||||
|
var input = $("#bytecode").html().replace(/(\r\n|\n|\r)/gm,"");
|
||||||
|
var file = parser.parse($("#bytecode").text());
|
||||||
|
print("<br />");
|
||||||
|
print(c0vm.execute(file, callbacks));
|
||||||
|
});
|
||||||
|
|
||||||
|
},{"./bytecode-parser":2,"./c0ffi.js":3,"./c0vm.js":4}],6:[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_CMPEQ",
|
||||||
|
0xA0: "IF_CMPNE",
|
||||||
|
0xA1: "IF_ICMPLT",
|
||||||
|
0xA2: "IF_ICMPGE",
|
||||||
|
0xA3: "IF_ICMPGT",
|
||||||
|
0xA4: "IF_ICMPLE",
|
||||||
|
0xA7: "GOTO",
|
||||||
|
0xBF: "ATHROW",
|
||||||
|
0xCF: "ASSERT",
|
||||||
|
0xB8: "INVOKESTATIC",
|
||||||
|
0xB7: "INVOKENATIVE",
|
||||||
|
0xB0: "RETURN"
|
||||||
|
};
|
||||||
|
|
||||||
|
},{}],7:[function(require,module,exports){
|
||||||
|
|
||||||
|
},{}]},{},[4,2,1,6,5]);
|
||||||
110
src/c0ffi.js
Normal file
110
src/c0ffi.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
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
|
||||||
|
|
||||||
243
src/c0vm.js
243
src/c0vm.js
@@ -1,243 +0,0 @@
|
|||||||
op = require("./opcodes");
|
|
||||||
|
|
||||||
var ProgramState = function(parsed_file) {
|
|
||||||
var main_function = parsed_file.function_pool[0];
|
|
||||||
|
|
||||||
this.stack = []
|
|
||||||
this.pc = 0;
|
|
||||||
this.program = main_function.code;
|
|
||||||
this.variables = [];
|
|
||||||
for (var i = 0; i < main_function.num_vars; i++)
|
|
||||||
variables.push(0);
|
|
||||||
this.file = parsed_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ProgramState.prototype.doIf = function(shouldJump) {
|
|
||||||
if (shouldJump) {
|
|
||||||
var address_offset = (this.program[this.pc+1] * 0x1000) +
|
|
||||||
this.program[this.pc+2];
|
|
||||||
this.pc += address_offset;
|
|
||||||
} else {
|
|
||||||
this.pc += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgramState.prototype.step = function() {
|
|
||||||
console.log("Running opcode " + op.lookup_table[this.program[this.pc]]);
|
|
||||||
switch (this.program[this.pc]) {
|
|
||||||
// Stack manipulation
|
|
||||||
case op.POP:
|
|
||||||
this.pc++;
|
|
||||||
this.stack.pop();
|
|
||||||
break;
|
|
||||||
case op.DUP:
|
|
||||||
this.pc++;
|
|
||||||
var v = this.stack.pop();
|
|
||||||
this.stack.push(v);
|
|
||||||
this.stack.push(v);
|
|
||||||
break;
|
|
||||||
case op.SWAP:
|
|
||||||
this.pc++;
|
|
||||||
var v1 = this.stack.pop();
|
|
||||||
var v2 = this.stack.pop();
|
|
||||||
this.stack.push(v1);
|
|
||||||
this.stack.push(v2);
|
|
||||||
break;
|
|
||||||
case op.BIPUSH:
|
|
||||||
this.pc += 2;
|
|
||||||
var val = this.program[this.pc-1];
|
|
||||||
|
|
||||||
// Do sign extension if necessary
|
|
||||||
if (val & 0x80 != 0)
|
|
||||||
val = -0x80 + (val & 0x7F);
|
|
||||||
this.stack.push(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Returning from a function
|
|
||||||
case op.RETURN:
|
|
||||||
var retVal = this.stack.pop();
|
|
||||||
throw retVal;
|
|
||||||
|
|
||||||
// Arithmetic
|
|
||||||
case op.IADD:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
console.log("Adding " + x + " and " + y);
|
|
||||||
this.stack.push((x+y) % 0x100000000);
|
|
||||||
break;
|
|
||||||
case op.ISUB:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
this.stack.push((x-y) % 0x100000000);
|
|
||||||
break;
|
|
||||||
case op.IMUL:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
this.stack.push((x*y) % 0x100000000);
|
|
||||||
break;
|
|
||||||
case op.IDIV:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
if (y == 0) c0_arith_error("Divide by zero");
|
|
||||||
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
|
||||||
|
|
||||||
// This does int division.
|
|
||||||
// As I understand it, the ~~ is treated as the identity on integers
|
|
||||||
// which forces the type to int, not float
|
|
||||||
this.stack.push(~~(x/y));
|
|
||||||
break;
|
|
||||||
case op.IREM:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
if (y == 0) c0_arith_error("Divide by zero");
|
|
||||||
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
|
|
||||||
this.stack.push(x%y);
|
|
||||||
break;
|
|
||||||
case op.IAND:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
this.stack.push(x&y);
|
|
||||||
break;
|
|
||||||
case op.IOR:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
this.stack.push(x|y);
|
|
||||||
break;
|
|
||||||
case op.IXOR:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
this.stack.push(x^y);
|
|
||||||
break;
|
|
||||||
case op.ISHL:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
|
|
||||||
this.stack.push(x<<y);
|
|
||||||
break;
|
|
||||||
case op.ISHR:
|
|
||||||
this.pc++;
|
|
||||||
var y = this.stack.pop();
|
|
||||||
var x = this.stack.pop();
|
|
||||||
if (y < 0 || y > 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
|
|
||||||
|
|
||||||
13
src/index.js
13
src/index.js
@@ -1,13 +0,0 @@
|
|||||||
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);
|
|
||||||
|
|
||||||
var file = parser.parse("../test/iadd.c0.bc0");
|
|
||||||
console.log("Result is " + c0vm.execute(file));
|
|
||||||
6
test/abort.c0
Normal file
6
test/abort.c0
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
error("assertion failure");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
25
test/abort.c0.bc0
Normal file
25
test/abort.c0.bc0
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 12 # string pool total size
|
||||||
|
# string pool
|
||||||
|
61 73 73 65 72 74 69 6F 6E 20 66 61 69 6C 75 72 65 00 # "assertion failure"
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 00 # number of local variables = 0
|
||||||
|
00 07 # code length = 7 bytes
|
||||||
|
14 00 00 # aldc 0 # s[0] = "assertion failure"
|
||||||
|
BF # athrow # error "assertion failure"
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
0
test/abort.c0.bc0out
Normal file
0
test/abort.c0.bc0out
Normal file
0
test/abort.c0.c0out
Normal file
0
test/abort.c0.c0out
Normal file
BIN
test/abort.c0.ex
Executable file
BIN
test/abort.c0.ex
Executable file
Binary file not shown.
129
test/arith.c0
Normal file
129
test/arith.c0
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int max; int min;
|
||||||
|
int x; int y; int z;
|
||||||
|
int constant;
|
||||||
|
|
||||||
|
//Testing overflow
|
||||||
|
max = 2147483647;
|
||||||
|
min = -2147483648;
|
||||||
|
y = max + 1;
|
||||||
|
printint(y);
|
||||||
|
print(" ");
|
||||||
|
y = min - 1;
|
||||||
|
printint(y);
|
||||||
|
print(" ");
|
||||||
|
// printint(min / -1);
|
||||||
|
|
||||||
|
//Testing multiplication of negatives
|
||||||
|
|
||||||
|
x = -25;
|
||||||
|
y = 15;
|
||||||
|
printint(x * y);
|
||||||
|
print(" ");
|
||||||
|
printint(-15 * -2147483648);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Divide by 0
|
||||||
|
// println("");
|
||||||
|
// printint(x / 0);
|
||||||
|
|
||||||
|
//Modulus by 0
|
||||||
|
// println("");
|
||||||
|
// printint(x % 0);
|
||||||
|
|
||||||
|
//Testing addition
|
||||||
|
x = -5;
|
||||||
|
y = -4;
|
||||||
|
printint(x + y);
|
||||||
|
z = x - y;
|
||||||
|
print(" ");
|
||||||
|
printint(z);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
|
||||||
|
//Division truncation
|
||||||
|
x = 25;
|
||||||
|
y = 2;
|
||||||
|
z = x / y;
|
||||||
|
printint(z);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
println("");
|
||||||
|
x = -25;
|
||||||
|
y = 2;
|
||||||
|
z = x / y;
|
||||||
|
printint(z);
|
||||||
|
print(" ");
|
||||||
|
x = -25;
|
||||||
|
y = -2;
|
||||||
|
z = x / y;
|
||||||
|
printint(z);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Modulus testing
|
||||||
|
print("Modulus testing ");
|
||||||
|
printint(235%32);
|
||||||
|
printint(-15%2);
|
||||||
|
print(" ");
|
||||||
|
printint(5%6);
|
||||||
|
print(" ");
|
||||||
|
printint(5%-2);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Testing constants
|
||||||
|
print("Testing constants ");
|
||||||
|
constant = -251;
|
||||||
|
printint(constant);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Testing inequalities
|
||||||
|
println("Testing inequalities ");
|
||||||
|
if(5>4) print("y1 "); else print("n1 ");
|
||||||
|
if(1>-1) print("y2 "); else print("n2 ");
|
||||||
|
if(0>=0) print("y3 "); else print("n3 ");
|
||||||
|
if(12945<-235) print("y4 "); else print("n4 ");
|
||||||
|
if(5<5) print("y5 "); else print("n5 ");
|
||||||
|
if(-5==5) print("y6 "); else print("n6 ");
|
||||||
|
if(15!=-15) print("y7 "); else print("n7 ");
|
||||||
|
|
||||||
|
//Testing bitwise operators
|
||||||
|
println("Testing bitwise operators ");
|
||||||
|
printint(0xF232C & 0xFF2352);
|
||||||
|
print(" ");
|
||||||
|
printint(0xF232C | 0xFF232);
|
||||||
|
print(" ");
|
||||||
|
printint(0xCD25 ^ 0x1D27);
|
||||||
|
print(" ");
|
||||||
|
printint(~0x2F32);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Testing bit shifting
|
||||||
|
println("Testing bit shifting");
|
||||||
|
printint(1<<31);
|
||||||
|
print(" ");
|
||||||
|
printint(23<<5);
|
||||||
|
print(" ");
|
||||||
|
printint(1>>5<<7);
|
||||||
|
print(" ");
|
||||||
|
printint(2352352>>2);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
//Default value for integers
|
||||||
|
// println("Testing default value for integers");
|
||||||
|
// printint(default_int);
|
||||||
|
// print(" ");
|
||||||
|
|
||||||
|
//Testing other arithmetic functions
|
||||||
|
printint(-6-25);
|
||||||
|
print(" ");
|
||||||
|
printint(6-25);
|
||||||
|
print(" ");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
println("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
430
test/arith.c0.bc0
Normal file
430
test/arith.c0.bc0
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 0F # int pool count
|
||||||
|
# int pool
|
||||||
|
7F FF FF FF
|
||||||
|
80 00 00 00
|
||||||
|
80 00 00 00
|
||||||
|
00 00 00 EB
|
||||||
|
FF FF FF 05
|
||||||
|
00 00 32 91
|
||||||
|
FF FF FF 15
|
||||||
|
00 0F 23 2C
|
||||||
|
00 FF 23 52
|
||||||
|
00 0F 23 2C
|
||||||
|
00 0F F2 32
|
||||||
|
00 00 CD 25
|
||||||
|
00 00 1D 27
|
||||||
|
00 00 2F 32
|
||||||
|
00 23 E4 E0
|
||||||
|
|
||||||
|
01 16 # string pool total size
|
||||||
|
# string pool
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
00 # ""
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
4D 6F 64 75 6C 75 73 20 74 65 73 74 69 6E 67 20 20 20 00 # "Modulus testing "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
54 65 73 74 69 6E 67 20 63 6F 6E 73 74 61 6E 74 73 20 20 20 00 # "Testing constants "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
54 65 73 74 69 6E 67 20 69 6E 65 71 75 61 6C 69 74 69 65 73 20 20 20 00 # "Testing inequalities "
|
||||||
|
79 31 20 20 00 # "y1 "
|
||||||
|
6E 31 20 20 00 # "n1 "
|
||||||
|
79 32 20 20 00 # "y2 "
|
||||||
|
6E 32 20 20 00 # "n2 "
|
||||||
|
79 33 20 20 00 # "y3 "
|
||||||
|
6E 33 20 20 00 # "n3 "
|
||||||
|
79 34 20 20 00 # "y4 "
|
||||||
|
6E 34 20 20 00 # "n4 "
|
||||||
|
79 35 20 20 00 # "y5 "
|
||||||
|
6E 35 20 20 00 # "n5 "
|
||||||
|
79 36 20 20 00 # "y6 "
|
||||||
|
6E 36 20 20 00 # "n6 "
|
||||||
|
79 37 20 20 00 # "y7 "
|
||||||
|
6E 37 20 20 00 # "n7 "
|
||||||
|
54 65 73 74 69 6E 67 20 62 69 74 77 69 73 65 20 6F 70 65 72 61 74 6F 72 73 20 20 20 00 # "Testing bitwise operators "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
54 65 73 74 69 6E 67 20 62 69 74 20 73 68 69 66 74 69 6E 67 00 # "Testing bit shifting"
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
20 20 20 00 # " "
|
||||||
|
00 # ""
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 06 # number of local variables = 6
|
||||||
|
02 C5 # code length = 709 bytes
|
||||||
|
13 00 00 # ildc 0 # c[0] = 2147483647
|
||||||
|
36 00 # vstore 0 # max = 2147483647;
|
||||||
|
13 00 01 # ildc 1 # c[1] = -2147483648
|
||||||
|
36 01 # vstore 1 # min = -(-2147483648);
|
||||||
|
15 00 # vload 0 # max
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd # (max + 1)
|
||||||
|
36 03 # vstore 3 # y = (max + 1);
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
B7 00 00 # invokenative 0 # printint(y)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 00 # aldc 0 # s[0] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 01 # vload 1 # min
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
64 # isub # (min - 1)
|
||||||
|
36 03 # vstore 3 # y = (min - 1);
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
B7 00 00 # invokenative 0 # printint(y)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 04 # aldc 4 # s[4] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 E7 # bipush -25 # -25
|
||||||
|
36 02 # vstore 2 # x = -(25);
|
||||||
|
10 0F # bipush 15 # 15
|
||||||
|
36 03 # vstore 3 # y = 15;
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
68 # imul # (x * y)
|
||||||
|
B7 00 00 # invokenative 0 # printint((x * y))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 08 # aldc 8 # s[8] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 F1 # bipush -15 # -15
|
||||||
|
13 00 02 # ildc 2 # c[2] = -2147483648
|
||||||
|
68 # imul # (-(15) * -(-2147483648))
|
||||||
|
B7 00 00 # invokenative 0 # printint((-(15) * -(-2147483648)))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 0C # aldc 12 # s[12] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 FB # bipush -5 # -5
|
||||||
|
36 02 # vstore 2 # x = -(5);
|
||||||
|
10 FC # bipush -4 # -4
|
||||||
|
36 03 # vstore 3 # y = -(4);
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
60 # iadd # (x + y)
|
||||||
|
B7 00 00 # invokenative 0 # printint((x + y))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
64 # isub # (x - y)
|
||||||
|
36 04 # vstore 4 # z = (x - y);
|
||||||
|
14 00 10 # aldc 16 # s[16] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 04 # vload 4 # z
|
||||||
|
B7 00 00 # invokenative 0 # printint(z)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 14 # aldc 20 # s[20] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 19 # bipush 25 # 25
|
||||||
|
36 02 # vstore 2 # x = 25;
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
36 03 # vstore 3 # y = 2;
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
6C # idiv # (x / y)
|
||||||
|
36 04 # vstore 4 # z = (x / y);
|
||||||
|
15 04 # vload 4 # z
|
||||||
|
B7 00 00 # invokenative 0 # printint(z)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 18 # aldc 24 # s[24] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 1C # aldc 28 # s[28] = ""
|
||||||
|
B7 00 02 # invokenative 2 # println("")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 E7 # bipush -25 # -25
|
||||||
|
36 02 # vstore 2 # x = -(25);
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
36 03 # vstore 3 # y = 2;
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
6C # idiv # (x / y)
|
||||||
|
36 04 # vstore 4 # z = (x / y);
|
||||||
|
15 04 # vload 4 # z
|
||||||
|
B7 00 00 # invokenative 0 # printint(z)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 1D # aldc 29 # s[29] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 E7 # bipush -25 # -25
|
||||||
|
36 02 # vstore 2 # x = -(25);
|
||||||
|
10 FE # bipush -2 # -2
|
||||||
|
36 03 # vstore 3 # y = -(2);
|
||||||
|
15 02 # vload 2 # x
|
||||||
|
15 03 # vload 3 # y
|
||||||
|
6C # idiv # (x / y)
|
||||||
|
36 04 # vstore 4 # z = (x / y);
|
||||||
|
15 04 # vload 4 # z
|
||||||
|
B7 00 00 # invokenative 0 # printint(z)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 21 # aldc 33 # s[33] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 25 # aldc 37 # s[37] = "Modulus testing "
|
||||||
|
B7 00 01 # invokenative 1 # print("Modulus testing ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 03 # ildc 3 # c[3] = 235
|
||||||
|
10 20 # bipush 32 # 32
|
||||||
|
70 # irem # (235 % 32)
|
||||||
|
B7 00 00 # invokenative 0 # printint((235 % 32))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 F1 # bipush -15 # -15
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
70 # irem # (-(15) % 2)
|
||||||
|
B7 00 00 # invokenative 0 # printint((-(15) % 2))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 38 # aldc 56 # s[56] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
10 06 # bipush 6 # 6
|
||||||
|
70 # irem # (5 % 6)
|
||||||
|
B7 00 00 # invokenative 0 # printint((5 % 6))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 3C # aldc 60 # s[60] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
10 FE # bipush -2 # -2
|
||||||
|
70 # irem # (5 % -(2))
|
||||||
|
B7 00 00 # invokenative 0 # printint((5 % -(2)))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 40 # aldc 64 # s[64] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 44 # aldc 68 # s[68] = "Testing constants "
|
||||||
|
B7 00 01 # invokenative 1 # print("Testing constants ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 04 # ildc 4 # c[4] = -251
|
||||||
|
36 05 # vstore 5 # constant = -(251);
|
||||||
|
15 05 # vload 5 # constant
|
||||||
|
B7 00 00 # invokenative 0 # printint(constant)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 59 # aldc 89 # s[89] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 5D # aldc 93 # s[93] = "Testing inequalities "
|
||||||
|
B7 00 02 # invokenative 2 # println("Testing inequalities ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
10 04 # bipush 4 # 4
|
||||||
|
A3 00 06 # if_icmpgt +6 # if (5 > 4) goto <00:then>
|
||||||
|
A7 00 0D # goto +13 # goto <01:else>
|
||||||
|
# <00:then>
|
||||||
|
14 00 75 # aldc 117 # s[117] = "y1 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y1 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <02:endif>
|
||||||
|
# <01:else>
|
||||||
|
14 00 7A # aldc 122 # s[122] = "n1 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n1 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <02:endif>
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
10 FF # bipush -1 # -1
|
||||||
|
A3 00 06 # if_icmpgt +6 # if (1 > -(1)) goto <03:then>
|
||||||
|
A7 00 0D # goto +13 # goto <04:else>
|
||||||
|
# <03:then>
|
||||||
|
14 00 7F # aldc 127 # s[127] = "y2 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y2 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <05:endif>
|
||||||
|
# <04:else>
|
||||||
|
14 00 84 # aldc 132 # s[132] = "n2 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n2 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <05:endif>
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
A2 00 06 # if_icmpge +6 # if (0 >= 0) goto <06:then>
|
||||||
|
A7 00 0D # goto +13 # goto <07:else>
|
||||||
|
# <06:then>
|
||||||
|
14 00 89 # aldc 137 # s[137] = "y3 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y3 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <08:endif>
|
||||||
|
# <07:else>
|
||||||
|
14 00 8E # aldc 142 # s[142] = "n3 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n3 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <08:endif>
|
||||||
|
13 00 05 # ildc 5 # c[5] = 12945
|
||||||
|
13 00 06 # ildc 6 # c[6] = -235
|
||||||
|
A1 00 06 # if_icmplt +6 # if (12945 < -(235)) goto <09:then>
|
||||||
|
A7 00 0D # goto +13 # goto <10:else>
|
||||||
|
# <09:then>
|
||||||
|
14 00 93 # aldc 147 # s[147] = "y4 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y4 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <11:endif>
|
||||||
|
# <10:else>
|
||||||
|
14 00 98 # aldc 152 # s[152] = "n4 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n4 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <11:endif>
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
A1 00 06 # if_icmplt +6 # if (5 < 5) goto <12:then>
|
||||||
|
A7 00 0D # goto +13 # goto <13:else>
|
||||||
|
# <12:then>
|
||||||
|
14 00 9D # aldc 157 # s[157] = "y5 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y5 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <14:endif>
|
||||||
|
# <13:else>
|
||||||
|
14 00 A2 # aldc 162 # s[162] = "n5 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n5 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <14:endif>
|
||||||
|
10 FB # bipush -5 # -5
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
9F 00 06 # if_cmpeq +6 # if (-(5) == 5) goto <15:then>
|
||||||
|
A7 00 0D # goto +13 # goto <16:else>
|
||||||
|
# <15:then>
|
||||||
|
14 00 A7 # aldc 167 # s[167] = "y6 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y6 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <17:endif>
|
||||||
|
# <16:else>
|
||||||
|
14 00 AC # aldc 172 # s[172] = "n6 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n6 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <17:endif>
|
||||||
|
10 0F # bipush 15 # 15
|
||||||
|
10 F1 # bipush -15 # -15
|
||||||
|
A0 00 06 # if_cmpne +6 # if (15 != -(15)) goto <18:then>
|
||||||
|
A7 00 0D # goto +13 # goto <19:else>
|
||||||
|
# <18:then>
|
||||||
|
14 00 B1 # aldc 177 # s[177] = "y7 "
|
||||||
|
B7 00 01 # invokenative 1 # print("y7 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
A7 00 0A # goto +10 # goto <20:endif>
|
||||||
|
# <19:else>
|
||||||
|
14 00 B6 # aldc 182 # s[182] = "n7 "
|
||||||
|
B7 00 01 # invokenative 1 # print("n7 ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
# <20:endif>
|
||||||
|
14 00 BB # aldc 187 # s[187] = "Testing bitwise operators "
|
||||||
|
B7 00 02 # invokenative 2 # println("Testing bitwise operators ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 07 # ildc 7 # c[7] = 992044
|
||||||
|
13 00 08 # ildc 8 # c[8] = 16720722
|
||||||
|
7E # iand # (992044 & 16720722)
|
||||||
|
B7 00 00 # invokenative 0 # printint((992044 & 16720722))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 D8 # aldc 216 # s[216] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 09 # ildc 9 # c[9] = 992044
|
||||||
|
13 00 0A # ildc 10 # c[10] = 1045042
|
||||||
|
80 # ior # (992044 | 1045042)
|
||||||
|
B7 00 00 # invokenative 0 # printint((992044 | 1045042))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 DC # aldc 220 # s[220] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 0B # ildc 11 # c[11] = 52517
|
||||||
|
13 00 0C # ildc 12 # c[12] = 7463
|
||||||
|
82 # ixor # (52517 ^ 7463)
|
||||||
|
B7 00 00 # invokenative 0 # printint((52517 ^ 7463))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 E0 # aldc 224 # s[224] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 0D # ildc 13 # c[13] = 12082
|
||||||
|
10 FF # bipush -1 #
|
||||||
|
82 # ixor # ~(12082)
|
||||||
|
B7 00 00 # invokenative 0 # printint(~(12082))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 E4 # aldc 228 # s[228] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 E8 # aldc 232 # s[232] = "Testing bit shifting"
|
||||||
|
B7 00 02 # invokenative 2 # println("Testing bit shifting")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
10 1F # bipush 31 # 31
|
||||||
|
78 # ishl # (1 << 31)
|
||||||
|
B7 00 00 # invokenative 0 # printint((1 << 31))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 00 FD # aldc 253 # s[253] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 17 # bipush 23 # 23
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
78 # ishl # (23 << 5)
|
||||||
|
B7 00 00 # invokenative 0 # printint((23 << 5))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 01 # aldc 257 # s[257] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
7A # ishr # (1 >> 5)
|
||||||
|
10 07 # bipush 7 # 7
|
||||||
|
78 # ishl # ((1 >> 5) << 7)
|
||||||
|
B7 00 00 # invokenative 0 # printint(((1 >> 5) << 7))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 05 # aldc 261 # s[261] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
13 00 0E # ildc 14 # c[14] = 2352352
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
7A # ishr # (2352352 >> 2)
|
||||||
|
B7 00 00 # invokenative 0 # printint((2352352 >> 2))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 09 # aldc 265 # s[265] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 FA # bipush -6 # -6
|
||||||
|
10 19 # bipush 25 # 25
|
||||||
|
64 # isub # (-(6) - 25)
|
||||||
|
B7 00 00 # invokenative 0 # printint((-(6) - 25))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 0D # aldc 269 # s[269] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 06 # bipush 6 # 6
|
||||||
|
10 19 # bipush 25 # 25
|
||||||
|
64 # isub # (6 - 25)
|
||||||
|
B7 00 00 # invokenative 0 # printint((6 - 25))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 11 # aldc 273 # s[273] = " "
|
||||||
|
B7 00 01 # invokenative 1 # print(" ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
14 01 15 # aldc 277 # s[277] = ""
|
||||||
|
B7 00 02 # invokenative 2 # println("")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 03 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 13 # printint
|
||||||
|
00 01 00 10 # print
|
||||||
|
00 01 00 14 # println
|
||||||
|
|
||||||
6
test/arith.c0.bc0out
Normal file
6
test/arith.c0.bc0out
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
-2147483648 2147483647 -375 -2147483648 -9 -1 12
|
||||||
|
-12 12 Modulus testing 11-1 5 1 Testing constants -251 Testing inequalities
|
||||||
|
y1 y2 y3 n4 n5 n6 y7 Testing bitwise operators
|
||||||
|
992000 1045310 53250 -12083 Testing bit shifting
|
||||||
|
-2147483648 736 0 588088 -31 -19
|
||||||
|
0
|
||||||
6
test/arith.c0.c0out
Normal file
6
test/arith.c0.c0out
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
-2147483648 2147483647 -375 -2147483648 -9 -1 12
|
||||||
|
-12 12 Modulus testing 11-1 5 1 Testing constants -251 Testing inequalities
|
||||||
|
y1 y2 y3 n4 n5 n6 y7 Testing bitwise operators
|
||||||
|
992000 1045310 53250 -12083 Testing bit shifting
|
||||||
|
-2147483648 736 0 588088 -31 -19
|
||||||
|
0
|
||||||
BIN
test/arith.c0.ex
Executable file
BIN
test/arith.c0.ex
Executable file
Binary file not shown.
12
test/arrays.c0
Normal file
12
test/arrays.c0
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int[] A = alloc_array(int, -2);
|
||||||
|
A[3] = 0;
|
||||||
|
A[3] = 1;
|
||||||
|
A[3] = 2;
|
||||||
|
A[3] = 3;
|
||||||
|
|
||||||
|
printint(A[3]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
52
test/arrays.c0.bc0
Normal file
52
test/arrays.c0.bc0
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 01 # number of local variables = 1
|
||||||
|
00 33 # code length = 51 bytes
|
||||||
|
10 FE # bipush -2 # -2
|
||||||
|
BC 04 # newarray 4 # alloc_array(int, -(2))
|
||||||
|
36 00 # vstore 0 # A = alloc_array(int, -(2));
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
4E # imstore # A[3] = 0;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
4E # imstore # A[3] = 1;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
4E # imstore # A[3] = 2;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
4E # imstore # A[3] = 3;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
2E # imload # A[3]
|
||||||
|
B7 00 00 # invokenative 0 # printint(A[3])
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 01 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 10 # printint
|
||||||
|
|
||||||
1
test/arrays.c0.bc0out
Normal file
1
test/arrays.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
30
|
||||||
0
test/arrays.c0.c0out
Normal file
0
test/arrays.c0.c0out
Normal file
BIN
test/arrays.c0.ex
Executable file
BIN
test/arrays.c0.ex
Executable file
Binary file not shown.
7
test/chararrays.c0
Normal file
7
test/chararrays.c0
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char[] A = alloc_array(char, 5);
|
||||||
|
printchar(A[3]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
23
test/dsquared.c0
Normal file
23
test/dsquared.c0
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
int dsquared(int x, int y)
|
||||||
|
{
|
||||||
|
return x*x + y*y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
int a1 = 15;
|
||||||
|
int b1 = 122;
|
||||||
|
int a2 = 42;
|
||||||
|
int b2 = 0;
|
||||||
|
int a3 = -7;
|
||||||
|
int b3 = -11;
|
||||||
|
int a4 = -4;
|
||||||
|
int b4 = 3;
|
||||||
|
int sum = 0;
|
||||||
|
sum = sum + dsquared(a1,b1);
|
||||||
|
sum = sum + dsquared(a2,b2);
|
||||||
|
sum = sum + dsquared(a3,b3);
|
||||||
|
sum = sum + dsquared(a4,b4);
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
78
test/dsquared.c0.bc0
Normal file
78
test/dsquared.c0.bc0
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 02 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 09 # number of local variables = 9
|
||||||
|
00 57 # code length = 87 bytes
|
||||||
|
10 0F # bipush 15 # 15
|
||||||
|
36 00 # vstore 0 # a1 = 15;
|
||||||
|
10 7A # bipush 122 # 122
|
||||||
|
36 01 # vstore 1 # b1 = 122;
|
||||||
|
10 2A # bipush 42 # 42
|
||||||
|
36 02 # vstore 2 # a2 = 42;
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 03 # vstore 3 # b2 = 0;
|
||||||
|
10 F9 # bipush -7 # -7
|
||||||
|
36 04 # vstore 4 # a3 = -(7);
|
||||||
|
10 F5 # bipush -11 # -11
|
||||||
|
36 05 # vstore 5 # b3 = -(11);
|
||||||
|
10 FC # bipush -4 # -4
|
||||||
|
36 06 # vstore 6 # a4 = -(4);
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
36 07 # vstore 7 # b4 = 3;
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 08 # vstore 8 # sum = 0;
|
||||||
|
15 08 # vload 8 # sum
|
||||||
|
15 00 # vload 0 # a1
|
||||||
|
15 01 # vload 1 # b1
|
||||||
|
B8 00 01 # invokestatic 1 # dsquared(a1, b1)
|
||||||
|
60 # iadd # (sum + dsquared(a1, b1))
|
||||||
|
36 08 # vstore 8 # sum = (sum + dsquared(a1, b1));
|
||||||
|
15 08 # vload 8 # sum
|
||||||
|
15 02 # vload 2 # a2
|
||||||
|
15 03 # vload 3 # b2
|
||||||
|
B8 00 01 # invokestatic 1 # dsquared(a2, b2)
|
||||||
|
60 # iadd # (sum + dsquared(a2, b2))
|
||||||
|
36 08 # vstore 8 # sum = (sum + dsquared(a2, b2));
|
||||||
|
15 08 # vload 8 # sum
|
||||||
|
15 04 # vload 4 # a3
|
||||||
|
15 05 # vload 5 # b3
|
||||||
|
B8 00 01 # invokestatic 1 # dsquared(a3, b3)
|
||||||
|
60 # iadd # (sum + dsquared(a3, b3))
|
||||||
|
36 08 # vstore 8 # sum = (sum + dsquared(a3, b3));
|
||||||
|
15 08 # vload 8 # sum
|
||||||
|
15 06 # vload 6 # a4
|
||||||
|
15 07 # vload 7 # b4
|
||||||
|
B8 00 01 # invokestatic 1 # dsquared(a4, b4)
|
||||||
|
60 # iadd # (sum + dsquared(a4, b4))
|
||||||
|
36 08 # vstore 8 # sum = (sum + dsquared(a4, b4));
|
||||||
|
15 08 # vload 8 # sum
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
|
||||||
|
#<dsquared>
|
||||||
|
00 02 # number of arguments = 2
|
||||||
|
00 02 # number of local variables = 2
|
||||||
|
00 0C # code length = 12 bytes
|
||||||
|
15 00 # vload 0 # x
|
||||||
|
15 00 # vload 0 # x
|
||||||
|
68 # imul # (x * x)
|
||||||
|
15 01 # vload 1 # y
|
||||||
|
15 01 # vload 1 # y
|
||||||
|
68 # imul # (y * y)
|
||||||
|
60 # iadd # ((x * x) + (y * y))
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/dsquared.c0.bc0out
Normal file
1
test/dsquared.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
17068
|
||||||
1
test/dsquared.c0.c0out
Normal file
1
test/dsquared.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
17068
|
||||||
BIN
test/dsquared.c0.ex
Executable file
BIN
test/dsquared.c0.ex
Executable file
Binary file not shown.
3
test/easyMath.c0
Normal file
3
test/easyMath.c0
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
int main() {
|
||||||
|
return (23 * 19)<<2;
|
||||||
|
}
|
||||||
26
test/easyMath.c0.bc0
Normal file
26
test/easyMath.c0.bc0
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 00 # number of local variables = 0
|
||||||
|
00 09 # code length = 9 bytes
|
||||||
|
10 17 # bipush 23 # 23
|
||||||
|
10 13 # bipush 19 # 19
|
||||||
|
68 # imul # (23 * 19)
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
78 # ishl # ((23 * 19) << 2)
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/easyMath.c0.bc0out
Normal file
1
test/easyMath.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1748
|
||||||
1
test/easyMath.c0.c0out
Normal file
1
test/easyMath.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1748
|
||||||
BIN
test/easyMath.c0.ex
Executable file
BIN
test/easyMath.c0.ex
Executable file
Binary file not shown.
9
test/hellosir.c0
Normal file
9
test/hellosir.c0
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#use <conio>
|
||||||
|
#use <string>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
print("What's your name? ");
|
||||||
|
string name = readline();
|
||||||
|
print(string_join("Hello, ", string_join(name, "!\n")));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
40
test/hellosir.c0.bc0
Normal file
40
test/hellosir.c0.bc0
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 1E # string pool total size
|
||||||
|
# string pool
|
||||||
|
57 68 61 74 27 73 20 79 6F 75 72 20 6E 61 6D 65 3F 20 00 # "What\'s your name\? "
|
||||||
|
48 65 6C 6C 6F 2C 20 00 # "Hello, "
|
||||||
|
21 0A 00 # "!\n"
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 01 # number of local variables = 1
|
||||||
|
00 21 # code length = 33 bytes
|
||||||
|
14 00 00 # aldc 0 # s[0] = "What\'s your name\? "
|
||||||
|
B7 00 00 # invokenative 0 # print("What\'s your name\? ")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
B7 00 01 # invokenative 1 # readline()
|
||||||
|
36 00 # vstore 0 # name = readline();
|
||||||
|
14 00 13 # aldc 19 # s[19] = "Hello, "
|
||||||
|
15 00 # vload 0 # name
|
||||||
|
14 00 1B # aldc 27 # s[27] = "!\n"
|
||||||
|
B7 00 02 # invokenative 2 # string_join(name, "!\n")
|
||||||
|
B7 00 02 # invokenative 2 # string_join("Hello, ", string_join(name, "!\n"))
|
||||||
|
B7 00 00 # invokenative 0 # print(string_join("Hello, ", string_join(name, "!\n")))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 03 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 06 # print
|
||||||
|
00 00 00 0B # readline
|
||||||
|
00 02 00 4F # string_join
|
||||||
|
|
||||||
2
test/hellosir.c0.bc0out
Normal file
2
test/hellosir.c0.bc0out
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
What's your name? Hello, uo!
|
||||||
|
0
|
||||||
2
test/hellosir.c0.c0out
Normal file
2
test/hellosir.c0.c0out
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
What's your name? Hello, hi!
|
||||||
|
0
|
||||||
BIN
test/hellosir.c0.ex
Executable file
BIN
test/hellosir.c0.ex
Executable file
Binary file not shown.
1
test/iadd.c0.bc0out
Normal file
1
test/iadd.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-2
|
||||||
1
test/iadd.c0.c0out
Normal file
1
test/iadd.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-2
|
||||||
BIN
test/iadd.c0.ex
Executable file
BIN
test/iadd.c0.ex
Executable file
Binary file not shown.
3
test/ishr.c0
Normal file
3
test/ishr.c0
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
int main () {
|
||||||
|
return -1 >> 1; /* should return -1 */
|
||||||
|
}
|
||||||
24
test/ishr.c0.bc0
Normal file
24
test/ishr.c0.bc0
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 00 # number of local variables = 0
|
||||||
|
00 06 # code length = 6 bytes
|
||||||
|
10 FF # bipush -1 # -1
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
7A # ishr # (-(1) >> 1)
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/ishr.c0.bc0out
Normal file
1
test/ishr.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-1
|
||||||
1
test/ishr.c0.c0out
Normal file
1
test/ishr.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
-1
|
||||||
BIN
test/ishr.c0.ex
Executable file
BIN
test/ishr.c0.ex
Executable file
Binary file not shown.
10
test/isqrt.c0
Normal file
10
test/isqrt.c0
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
int main () {
|
||||||
|
int n = 15122;
|
||||||
|
int i = 0; int k = 0;
|
||||||
|
while (k <= n) {
|
||||||
|
k += 2*i + 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i-1;
|
||||||
|
}
|
||||||
|
|
||||||
51
test/isqrt.c0.bc0
Normal file
51
test/isqrt.c0.bc0
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 01 # int pool count
|
||||||
|
# int pool
|
||||||
|
00 00 3B 12
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 03 # number of local variables = 3
|
||||||
|
00 34 # code length = 52 bytes
|
||||||
|
13 00 00 # ildc 0 # c[0] = 15122
|
||||||
|
36 00 # vstore 0 # n = 15122;
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 01 # vstore 1 # i = 0;
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 02 # vstore 2 # k = 0;
|
||||||
|
# <00:loop>
|
||||||
|
15 02 # vload 2 # k
|
||||||
|
15 00 # vload 0 # n
|
||||||
|
A4 00 06 # if_icmple +6 # if (k <= n) goto <01:body>
|
||||||
|
A7 00 1A # goto +26 # goto <02:exit>
|
||||||
|
# <01:body>
|
||||||
|
15 02 # vload 2 # k
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
15 01 # vload 1 # i
|
||||||
|
68 # imul # (2 * i)
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd # ((2 * i) + 1)
|
||||||
|
60 # iadd #
|
||||||
|
36 02 # vstore 2 # k += ((2 * i) + 1);
|
||||||
|
15 01 # vload 1 # i
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd #
|
||||||
|
36 01 # vstore 1 # i += 1;
|
||||||
|
A7 FF E2 # goto -30 # goto <00:loop>
|
||||||
|
# <02:exit>
|
||||||
|
15 01 # vload 1 # i
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
64 # isub # (i - 1)
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
0
test/isqrt.c0.bc0out
Normal file
0
test/isqrt.c0.bc0out
Normal file
1
test/isqrt.c0.c0out
Normal file
1
test/isqrt.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
122
|
||||||
BIN
test/isqrt.c0.ex
Executable file
BIN
test/isqrt.c0.ex
Executable file
Binary file not shown.
10
test/mid.c0
Normal file
10
test/mid.c0
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
int main()
|
||||||
|
{
|
||||||
|
int low = 0x15;
|
||||||
|
int high = 0x122;
|
||||||
|
int mid;
|
||||||
|
|
||||||
|
mid = low + (high - low)/2;
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
35
test/mid.c0.bc0
Normal file
35
test/mid.c0.bc0
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 01 # int pool count
|
||||||
|
# int pool
|
||||||
|
00 00 01 22
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 03 # number of local variables = 3
|
||||||
|
00 19 # code length = 25 bytes
|
||||||
|
10 15 # bipush 21 # 21
|
||||||
|
36 00 # vstore 0 # low = 21;
|
||||||
|
13 00 00 # ildc 0 # c[0] = 290
|
||||||
|
36 01 # vstore 1 # high = 290;
|
||||||
|
15 00 # vload 0 # low
|
||||||
|
15 01 # vload 1 # high
|
||||||
|
15 00 # vload 0 # low
|
||||||
|
64 # isub # (high - low)
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
6C # idiv # ((high - low) / 2)
|
||||||
|
60 # iadd # (low + ((high - low) / 2))
|
||||||
|
36 02 # vstore 2 # mid = (low + ((high - low) / 2));
|
||||||
|
15 02 # vload 2 # mid
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/mid.c0.bc0out
Normal file
1
test/mid.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
155
|
||||||
1
test/mid.c0.c0out
Normal file
1
test/mid.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
155
|
||||||
BIN
test/mid.c0.ex
Executable file
BIN
test/mid.c0.ex
Executable file
Binary file not shown.
10
test/moreArrays.c0
Normal file
10
test/moreArrays.c0
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int[] A = alloc_array(int, 50);
|
||||||
|
A[3] = 23;
|
||||||
|
A[2] = 12;
|
||||||
|
printint(A[3]);
|
||||||
|
printint(A[2]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
48
test/moreArrays.c0.bc0
Normal file
48
test/moreArrays.c0.bc0
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 01 # number of local variables = 1
|
||||||
|
00 2D # code length = 45 bytes
|
||||||
|
10 32 # bipush 50 # 50
|
||||||
|
BC 04 # newarray 4 # alloc_array(int, 50)
|
||||||
|
36 00 # vstore 0 # A = alloc_array(int, 50);
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
10 17 # bipush 23 # 23
|
||||||
|
4E # imstore # A[3] = 23;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
63 # aadds # &A[2]
|
||||||
|
10 0C # bipush 12 # 12
|
||||||
|
4E # imstore # A[2] = 12;
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
63 # aadds # &A[3]
|
||||||
|
2E # imload # A[3]
|
||||||
|
B7 00 00 # invokenative 0 # printint(A[3])
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 00 # vload 0 # A
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
63 # aadds # &A[2]
|
||||||
|
2E # imload # A[2]
|
||||||
|
B7 00 00 # invokenative 0 # printint(A[2])
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 01 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 13 # printint
|
||||||
|
|
||||||
1
test/moreArrays.c0.bc0out
Normal file
1
test/moreArrays.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
23120
|
||||||
1
test/moreArrays.c0.c0out
Normal file
1
test/moreArrays.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
23120
|
||||||
BIN
test/moreArrays.c0.ex
Executable file
BIN
test/moreArrays.c0.ex
Executable file
Binary file not shown.
22
test/piazza1.c0
Normal file
22
test/piazza1.c0
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
struct s
|
||||||
|
{
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int[] a;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct s* example=alloc(struct s);
|
||||||
|
example->y=5;
|
||||||
|
example->x=6;
|
||||||
|
int x = example->x + 1;
|
||||||
|
example->a=alloc_array(int,4);
|
||||||
|
example->a[0] = 5;
|
||||||
|
int y = example->a[0];
|
||||||
|
example->a[0]=3;
|
||||||
|
//@assert(\length(example->a)==4);
|
||||||
|
return example->x + x +y;
|
||||||
|
}
|
||||||
70
test/piazza1.c0.bc0
Normal file
70
test/piazza1.c0.bc0
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 03 # number of local variables = 3
|
||||||
|
00 52 # code length = 82 bytes
|
||||||
|
BB 10 # new 16 # alloc(struct s)
|
||||||
|
36 00 # vstore 0 # example = alloc(struct s);
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 04 # aaddf 4 # &example->y
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
4E # imstore # example->y = 5;
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 00 # aaddf 0 # &example->x
|
||||||
|
10 06 # bipush 6 # 6
|
||||||
|
4E # imstore # example->x = 6;
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 00 # aaddf 0 # &example->x
|
||||||
|
2E # imload # example->x
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd # (example->x + 1)
|
||||||
|
36 01 # vstore 1 # x = (example->x + 1);
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 08 # aaddf 8 # &example->a
|
||||||
|
10 04 # bipush 4 # 4
|
||||||
|
BC 04 # newarray 4 # alloc_array(int, 4)
|
||||||
|
4F # amstore # example->a = alloc_array(int, 4);
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 08 # aaddf 8 # &example->a
|
||||||
|
2F # amload # example->a
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
63 # aadds # &example->a[0]
|
||||||
|
10 05 # bipush 5 # 5
|
||||||
|
4E # imstore # example->a[0] = 5;
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 08 # aaddf 8 # &example->a
|
||||||
|
2F # amload # example->a
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
63 # aadds # &example->a[0]
|
||||||
|
2E # imload # example->a[0]
|
||||||
|
36 02 # vstore 2 # y = example->a[0];
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 08 # aaddf 8 # &example->a
|
||||||
|
2F # amload # example->a
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
63 # aadds # &example->a[0]
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
4E # imstore # example->a[0] = 3;
|
||||||
|
15 00 # vload 0 # example
|
||||||
|
62 00 # aaddf 0 # &example->x
|
||||||
|
2E # imload # example->x
|
||||||
|
15 01 # vload 1 # x
|
||||||
|
60 # iadd # (example->x + x)
|
||||||
|
15 02 # vload 2 # y
|
||||||
|
60 # iadd # ((example->x + x) + y)
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/piazza1.c0.bc0out
Normal file
1
test/piazza1.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
18
|
||||||
1
test/piazza1.c0.c0out
Normal file
1
test/piazza1.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
18
|
||||||
BIN
test/piazza1.c0.ex
Executable file
BIN
test/piazza1.c0.ex
Executable file
Binary file not shown.
7
test/sample2.5.c0
Normal file
7
test/sample2.5.c0
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
int main () {
|
||||||
|
int i; int sum = 0;
|
||||||
|
for (i = 15; i <= 122; i++)
|
||||||
|
sum += i;
|
||||||
|
assert(sum == 0);
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
55
test/sample2.5.c0.bc0
Normal file
55
test/sample2.5.c0.bc0
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 25 # string pool total size
|
||||||
|
# string pool
|
||||||
|
73 61 6D 70 6C 65 32 2E 35 2E 63 30 3A 35 2E 32 2D 35 2E 31 39 3A 20 61 73 73 65 72 74 20 66 61 69 6C 65 64 00 # "sample2.5.c0:5.2-5.19: assert failed"
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 02 # number of local variables = 2
|
||||||
|
00 3B # code length = 59 bytes
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 01 # vstore 1 # sum = 0;
|
||||||
|
10 0F # bipush 15 # 15
|
||||||
|
36 00 # vstore 0 # i = 15;
|
||||||
|
# <00:loop>
|
||||||
|
15 00 # vload 0 # i
|
||||||
|
10 7A # bipush 122 # 122
|
||||||
|
A4 00 06 # if_icmple +6 # if (i <= 122) goto <01:body>
|
||||||
|
A7 00 14 # goto +20 # goto <02:exit>
|
||||||
|
# <01:body>
|
||||||
|
15 01 # vload 1 # sum
|
||||||
|
15 00 # vload 0 # i
|
||||||
|
60 # iadd #
|
||||||
|
36 01 # vstore 1 # sum += i;
|
||||||
|
15 00 # vload 0 # i
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd #
|
||||||
|
36 00 # vstore 0 # i += 1;
|
||||||
|
A7 FF E8 # goto -24 # goto <00:loop>
|
||||||
|
# <02:exit>
|
||||||
|
15 01 # vload 1 # sum
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
9F 00 06 # if_cmpeq +6 # if (sum == 0) goto <03:cond_true>
|
||||||
|
A7 00 08 # goto +8 # goto <04:cond_false>
|
||||||
|
# <03:cond_true>
|
||||||
|
10 01 # bipush 1 # true
|
||||||
|
A7 00 05 # goto +5 # goto <05:cond_end>
|
||||||
|
# <04:cond_false>
|
||||||
|
10 00 # bipush 0 # false
|
||||||
|
# <05:cond_end>
|
||||||
|
14 00 00 # aldc 0 # s[0] = "sample2.5.c0:5.2-5.19: assert failed"
|
||||||
|
CF # assert # assert(sum == 0) [failure message on stack]
|
||||||
|
15 01 # vload 1 # sum
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
0
test/sample2.5.c0.bc0out
Normal file
0
test/sample2.5.c0.bc0out
Normal file
0
test/sample2.5.c0.c0out
Normal file
0
test/sample2.5.c0.c0out
Normal file
BIN
test/sample2.5.c0.ex
Executable file
BIN
test/sample2.5.c0.ex
Executable file
Binary file not shown.
29
test/strings.c0
Normal file
29
test/strings.c0
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#use <conio>
|
||||||
|
#use <string>
|
||||||
|
|
||||||
|
char char_tolower(char c) {
|
||||||
|
int ccode = char_ord(c);
|
||||||
|
if (char_ord('A') <= ccode && ccode <= char_ord('Z')) {
|
||||||
|
int shift = char_ord('a') - char_ord('A');
|
||||||
|
return char_chr(ccode + shift);
|
||||||
|
} else {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string string_lower(string s)
|
||||||
|
//@ensures string_length(s) == string_length(\result);
|
||||||
|
{
|
||||||
|
int len = string_length(s);
|
||||||
|
char[] A = string_to_chararray(s);
|
||||||
|
char[] B = alloc_array(char, len+1);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
B[i] = char_tolower(A[i]);
|
||||||
|
B[len] = '\0'; /* redundant */
|
||||||
|
return string_from_chararray(B);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
print (string_lower("HEllo There!?"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
118
test/strings.c0.bc0
Normal file
118
test/strings.c0.bc0
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 0E # string pool total size
|
||||||
|
# string pool
|
||||||
|
48 45 6C 6C 6F 20 54 68 65 72 65 21 3F 00 # "HEllo There!\?"
|
||||||
|
|
||||||
|
00 03 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 05 # number of local variables = 5
|
||||||
|
00 0D # code length = 13 bytes
|
||||||
|
14 00 00 # aldc 0 # s[0] = "HEllo There!\?"
|
||||||
|
B8 00 02 # invokestatic 2 # string_lower("HEllo There!\?")
|
||||||
|
B7 00 05 # invokenative 5 # print(string_lower("HEllo There!\?"))
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
|
||||||
|
#<char_tolower>
|
||||||
|
00 01 # number of arguments = 1
|
||||||
|
00 03 # number of local variables = 3
|
||||||
|
00 3D # code length = 61 bytes
|
||||||
|
15 00 # vload 0 # c
|
||||||
|
B7 00 00 # invokenative 0 # char_ord(c)
|
||||||
|
36 01 # vstore 1 # ccode = char_ord(c);
|
||||||
|
10 41 # bipush 65 # 'A'
|
||||||
|
B7 00 00 # invokenative 0 # char_ord('A')
|
||||||
|
15 01 # vload 1 # ccode
|
||||||
|
A4 00 06 # if_icmple +6 # if (char_ord('A') <= ccode) goto <03:and>
|
||||||
|
A7 00 29 # goto +41 # goto <01:else>
|
||||||
|
# <03:and>
|
||||||
|
15 01 # vload 1 # ccode
|
||||||
|
10 5A # bipush 90 # 'Z'
|
||||||
|
B7 00 00 # invokenative 0 # char_ord('Z')
|
||||||
|
A4 00 06 # if_icmple +6 # if (ccode <= char_ord('Z')) goto <00:then>
|
||||||
|
A7 00 1C # goto +28 # goto <01:else>
|
||||||
|
# <00:then>
|
||||||
|
10 61 # bipush 97 # 'a'
|
||||||
|
B7 00 00 # invokenative 0 # char_ord('a')
|
||||||
|
10 41 # bipush 65 # 'A'
|
||||||
|
B7 00 00 # invokenative 0 # char_ord('A')
|
||||||
|
64 # isub # (char_ord('a') - char_ord('A'))
|
||||||
|
36 02 # vstore 2 # shift = (char_ord('a') - char_ord('A'));
|
||||||
|
15 01 # vload 1 # ccode
|
||||||
|
15 02 # vload 2 # shift
|
||||||
|
60 # iadd # (ccode + shift)
|
||||||
|
B7 00 01 # invokenative 1 # char_chr((ccode + shift))
|
||||||
|
B0 # return #
|
||||||
|
A7 00 06 # goto +6 # goto <02:endif>
|
||||||
|
# <01:else>
|
||||||
|
15 00 # vload 0 # c
|
||||||
|
B0 # return #
|
||||||
|
# <02:endif>
|
||||||
|
|
||||||
|
|
||||||
|
#<string_lower>
|
||||||
|
00 01 # number of arguments = 1
|
||||||
|
00 05 # number of local variables = 5
|
||||||
|
00 4C # code length = 76 bytes
|
||||||
|
15 00 # vload 0 # s
|
||||||
|
B7 00 02 # invokenative 2 # string_length(s)
|
||||||
|
36 01 # vstore 1 # len = string_length(s);
|
||||||
|
15 00 # vload 0 # s
|
||||||
|
B7 00 03 # invokenative 3 # string_to_chararray(s)
|
||||||
|
36 02 # vstore 2 # A = string_to_chararray(s);
|
||||||
|
15 01 # vload 1 # len
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd # (len + 1)
|
||||||
|
BC 01 # newarray 1 # alloc_array(char, (len + 1))
|
||||||
|
36 03 # vstore 3 # B = alloc_array(char, (len + 1));
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
36 04 # vstore 4 # i = 0;
|
||||||
|
# <04:loop>
|
||||||
|
15 04 # vload 4 # i
|
||||||
|
15 01 # vload 1 # len
|
||||||
|
A1 00 06 # if_icmplt +6 # if (i < len) goto <05:body>
|
||||||
|
A7 00 1C # goto +28 # goto <06:exit>
|
||||||
|
# <05:body>
|
||||||
|
15 03 # vload 3 # B
|
||||||
|
15 04 # vload 4 # i
|
||||||
|
63 # aadds # &B[i]
|
||||||
|
15 02 # vload 2 # A
|
||||||
|
15 04 # vload 4 # i
|
||||||
|
63 # aadds # &A[i]
|
||||||
|
34 # cmload # A[i]
|
||||||
|
B8 00 01 # invokestatic 1 # char_tolower(A[i])
|
||||||
|
55 # cmstore # B[i] = char_tolower(A[i]);
|
||||||
|
15 04 # vload 4 # i
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
60 # iadd #
|
||||||
|
36 04 # vstore 4 # i += 1;
|
||||||
|
A7 FF E0 # goto -32 # goto <04:loop>
|
||||||
|
# <06:exit>
|
||||||
|
15 03 # vload 3 # B
|
||||||
|
15 01 # vload 1 # len
|
||||||
|
63 # aadds # &B[len]
|
||||||
|
10 00 # bipush 0 # '\000'
|
||||||
|
55 # cmstore # B[len] = '\0';
|
||||||
|
15 03 # vload 3 # B
|
||||||
|
B7 00 04 # invokenative 4 # string_from_chararray(B)
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 06 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 51 # char_ord
|
||||||
|
00 01 00 50 # char_chr
|
||||||
|
00 01 00 5A # string_length
|
||||||
|
00 01 00 5D # string_to_chararray
|
||||||
|
00 01 00 55 # string_from_chararray
|
||||||
|
00 01 00 10 # print
|
||||||
|
|
||||||
1
test/strings.c0.bc0out
Normal file
1
test/strings.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello there!?0
|
||||||
1
test/strings.c0.c0out
Normal file
1
test/strings.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello there!?0
|
||||||
BIN
test/strings.c0.ex
Executable file
BIN
test/strings.c0.ex
Executable file
Binary file not shown.
18
test/structs.c0
Normal file
18
test/structs.c0
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
struct test {
|
||||||
|
int a;
|
||||||
|
string b;
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
struct test* t = alloc(struct test);
|
||||||
|
t->a = 1;
|
||||||
|
t->b = "potato chip";
|
||||||
|
t->c = 23;
|
||||||
|
print(t->b);
|
||||||
|
printint(t->a);
|
||||||
|
printint(t->c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
54
test/structs.c0.bc0
Normal file
54
test/structs.c0.bc0
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 0C # string pool total size
|
||||||
|
# string pool
|
||||||
|
70 6F 74 61 74 6F 20 63 68 69 70 00 # "potato chip"
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 01 # number of local variables = 1
|
||||||
|
00 38 # code length = 56 bytes
|
||||||
|
BB 18 # new 24 # alloc(struct test)
|
||||||
|
36 00 # vstore 0 # t = alloc(struct test);
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 00 # aaddf 0 # &t->a
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
4E # imstore # t->a = 1;
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 08 # aaddf 8 # &t->b
|
||||||
|
14 00 00 # aldc 0 # s[0] = "potato chip"
|
||||||
|
4F # amstore # t->b = "potato chip";
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 10 # aaddf 16 # &t->c
|
||||||
|
10 17 # bipush 23 # 23
|
||||||
|
4E # imstore # t->c = 23;
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 08 # aaddf 8 # &t->b
|
||||||
|
2F # amload # t->b
|
||||||
|
B7 00 00 # invokenative 0 # print(t->b)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 00 # aaddf 0 # &t->a
|
||||||
|
2E # imload # t->a
|
||||||
|
B7 00 01 # invokenative 1 # printint(t->a)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
15 00 # vload 0 # t
|
||||||
|
62 10 # aaddf 16 # &t->c
|
||||||
|
2E # imload # t->c
|
||||||
|
B7 00 01 # invokenative 1 # printint(t->c)
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 00 # bipush 0 # 0
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 02 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 10 # print
|
||||||
|
00 01 00 13 # printint
|
||||||
|
|
||||||
1
test/structs.c0.bc0out
Normal file
1
test/structs.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
potato chip1230
|
||||||
1
test/structs.c0.c0out
Normal file
1
test/structs.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
potato chip1230
|
||||||
BIN
test/structs.c0.ex
Executable file
BIN
test/structs.c0.ex
Executable file
Binary file not shown.
25
test/swapTest.c0.bc0
Normal file
25
test/swapTest.c0.bc0
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 00 # number of local variables = 0
|
||||||
|
00 07 # code length = 6 bytes
|
||||||
|
10 FF # bipush -1 # -1
|
||||||
|
10 23
|
||||||
|
5F
|
||||||
|
57
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
7
test/testError.c0
Normal file
7
test/testError.c0
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#use <conio>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
assert(2==2);
|
||||||
|
print("yolomode");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
40
test/testError.c0.bc0
Normal file
40
test/testError.c0.bc0
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 2E # string pool total size
|
||||||
|
# string pool
|
||||||
|
74 65 73 74 45 72 72 6F 72 2E 63 30 3A 34 2E 33 2D 34 2E 31 36 3A 20 61 73 73 65 72 74 20 66 61 69 6C 65 64 00 # "testError.c0:4.3-4.16: assert failed"
|
||||||
|
79 6F 6C 6F 6D 6F 64 65 00 # "yolomode"
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 00 # number of local variables = 0
|
||||||
|
00 1F # code length = 31 bytes
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
10 02 # bipush 2 # 2
|
||||||
|
9F 00 06 # if_cmpeq +6 # if (2 == 2) goto <00:cond_true>
|
||||||
|
A7 00 08 # goto +8 # goto <01:cond_false>
|
||||||
|
# <00:cond_true>
|
||||||
|
10 01 # bipush 1 # true
|
||||||
|
A7 00 05 # goto +5 # goto <02:cond_end>
|
||||||
|
# <01:cond_false>
|
||||||
|
10 00 # bipush 0 # false
|
||||||
|
# <02:cond_end>
|
||||||
|
14 00 00 # aldc 0 # s[0] = "testError.c0:4.3-4.16: assert failed"
|
||||||
|
CF # assert # assert(2 == 2) [failure message on stack]
|
||||||
|
14 00 25 # aldc 37 # s[37] = "yolomode"
|
||||||
|
B7 00 00 # invokenative 0 # print("yolomode")
|
||||||
|
57 # pop # (ignore result)
|
||||||
|
10 01 # bipush 1 # 1
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 01 # native count
|
||||||
|
# native pool
|
||||||
|
00 01 00 06 # print
|
||||||
|
|
||||||
1
test/testError.c0.bc0out
Normal file
1
test/testError.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
yolomode1
|
||||||
1
test/testError.c0.c0out
Normal file
1
test/testError.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
yolomode1
|
||||||
BIN
test/testError.c0.ex
Executable file
BIN
test/testError.c0.ex
Executable file
Binary file not shown.
8
test/testif.c0
Normal file
8
test/testif.c0
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
int main() {
|
||||||
|
int x = 4;
|
||||||
|
if (x < 3)
|
||||||
|
x = 23;
|
||||||
|
else
|
||||||
|
x = 32;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
36
test/testif.c0.bc0
Normal file
36
test/testif.c0.bc0
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
C0 C0 FF EE # magic number
|
||||||
|
00 09 # version 4, arch = 1 (64 bits)
|
||||||
|
|
||||||
|
00 00 # int pool count
|
||||||
|
# int pool
|
||||||
|
|
||||||
|
00 00 # string pool total size
|
||||||
|
# string pool
|
||||||
|
|
||||||
|
00 01 # function count
|
||||||
|
# function_pool
|
||||||
|
|
||||||
|
#<main>
|
||||||
|
00 00 # number of arguments = 0
|
||||||
|
00 01 # number of local variables = 1
|
||||||
|
00 1C # code length = 28 bytes
|
||||||
|
10 04 # bipush 4 # 4
|
||||||
|
36 00 # vstore 0 # x = 4;
|
||||||
|
15 00 # vload 0 # x
|
||||||
|
10 03 # bipush 3 # 3
|
||||||
|
A1 00 06 # if_icmplt +6 # if (x < 3) goto <00:then>
|
||||||
|
A7 00 0A # goto +10 # goto <01:else>
|
||||||
|
# <00:then>
|
||||||
|
10 17 # bipush 23 # 23
|
||||||
|
36 00 # vstore 0 # x = 23;
|
||||||
|
A7 00 07 # goto +7 # goto <02:endif>
|
||||||
|
# <01:else>
|
||||||
|
10 20 # bipush 32 # 32
|
||||||
|
36 00 # vstore 0 # x = 32;
|
||||||
|
# <02:endif>
|
||||||
|
15 00 # vload 0 # x
|
||||||
|
B0 # return #
|
||||||
|
|
||||||
|
00 00 # native count
|
||||||
|
# native pool
|
||||||
|
|
||||||
1
test/testif.c0.bc0out
Normal file
1
test/testif.c0.bc0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
32
|
||||||
1
test/testif.c0.c0out
Normal file
1
test/testif.c0.c0out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
32
|
||||||
BIN
test/testif.c0.ex
Executable file
BIN
test/testif.c0.ex
Executable file
Binary file not shown.
135
test/tests.js
Normal file
135
test/tests.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
parser = require("../src/bytecode-parser.js");
|
||||||
|
c0vm = require("../src/c0vm.js");
|
||||||
|
c0ffi = require("../src/c0ffi.js");
|
||||||
|
|
||||||
|
var callbacks = {}
|
||||||
|
var printout = "";
|
||||||
|
|
||||||
|
callbacks[c0ffi.NATIVE_PRINT] = function(args) {
|
||||||
|
printout += args[0];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks[c0ffi.NATIVE_PRINTINT] = function(args) {
|
||||||
|
printout += args[0];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks[c0ffi.NATIVE_PRINTLN] = function(args) {
|
||||||
|
printout += (args[0] + "\n");
|
||||||
|
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);
|
||||||
|
test.ok(result == expected_result,
|
||||||
|
filename + " - did not get expected result " + expected_result +
|
||||||
|
", instead got " + result);
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testIADD = doTest("iadd.c0.bc0", -2);
|
||||||
|
|
||||||
|
exports.testPrint = function(test) {
|
||||||
|
printout = "";
|
||||||
|
var result = c0vm.execute(parser.parse("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();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testISHR = doTest("ishr.c0.bc0", -1);
|
||||||
|
|
||||||
|
exports.testISQRT = doTest("isqrt.c0.bc0", 122);
|
||||||
|
|
||||||
|
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)
|
||||||
|
});
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testIF = doTest("testif.c0.bc0", 32);
|
||||||
|
|
||||||
|
exports.testDSQUARED = doTest("dsquared.c0.bc0", 17068);
|
||||||
|
|
||||||
|
exports.testArrays = function(test) {
|
||||||
|
test.throws(function () {
|
||||||
|
c0vm.execute(parser.parse("arrays.c0.bc0"), callbacks, false)
|
||||||
|
});
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testMoreArray = function(test) {
|
||||||
|
printout = "";
|
||||||
|
var result = c0vm.execute(parser.parse("moreArrays.c0.bc0"), callbacks, false);
|
||||||
|
test.ok(printout == "2312",
|
||||||
|
"moreArrays.c0.bc0 - Did not print to screen correctly, result was " +
|
||||||
|
printout);
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testStructs = function(test) {
|
||||||
|
printout = "";
|
||||||
|
var result = c0vm.execute(parser.parse("structs.c0.bc0"), callbacks, false);
|
||||||
|
test.ok(printout == "potato chip123",
|
||||||
|
"structs.c0.bc0 - Did not print to screen correctly, result was " +
|
||||||
|
printout);
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testAbort = function(test) {
|
||||||
|
test.throws(function () {
|
||||||
|
c0vm.execute(parser.parse("abort.c0.bc0"), callbacks, false);
|
||||||
|
});
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testArith = function(test) {
|
||||||
|
printout = "";
|
||||||
|
var result = c0vm.execute(parser.parse("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);
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.testPIAZZA1 = doTest("piazza1.c0.bc0", 18);
|
||||||
|
|
||||||
|
exports.testSTRINGS = function(test) {
|
||||||
|
printout = "";
|
||||||
|
var result = c0vm.execute(parser.parse("strings.c0.bc0"), callbacks, false);
|
||||||
|
test.ok(printout == "hello there!?",
|
||||||
|
"strings.c0.bc0 - Did not print to screen correctly, result was " +
|
||||||
|
printout);
|
||||||
|
test.done();
|
||||||
|
}
|
||||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user