Merge branch 'run_vm'

Adds basic support for running c0 in browser
This commit is contained in:
2015-04-13 23:16:06 -04:00
101 changed files with 3444 additions and 281 deletions

View File

@@ -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
View 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

View File

@@ -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) {

View File

@@ -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
View 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
View 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
View 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));
});

View File

@@ -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
View 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
View 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

View File

@@ -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

View File

@@ -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
View File

@@ -0,0 +1,6 @@
#use <conio>
int main () {
error("assertion failure");
return 0;
}

25
test/abort.c0.bc0 Normal file
View 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
View File

0
test/abort.c0.c0out Normal file
View File

BIN
test/abort.c0.ex Executable file

Binary file not shown.

129
test/arith.c0 Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

12
test/arrays.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
30

0
test/arrays.c0.c0out Normal file
View File

BIN
test/arrays.c0.ex Executable file

Binary file not shown.

7
test/chararrays.c0 Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1 @@
17068

1
test/dsquared.c0.c0out Normal file
View File

@@ -0,0 +1 @@
17068

BIN
test/dsquared.c0.ex Executable file

Binary file not shown.

3
test/easyMath.c0 Normal file
View File

@@ -0,0 +1,3 @@
int main() {
return (23 * 19)<<2;
}

26
test/easyMath.c0.bc0 Normal file
View 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
View File

@@ -0,0 +1 @@
1748

1
test/easyMath.c0.c0out Normal file
View File

@@ -0,0 +1 @@
1748

BIN
test/easyMath.c0.ex Executable file

Binary file not shown.

9
test/hellosir.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1,2 @@
What's your name? Hello, uo!
0

2
test/hellosir.c0.c0out Normal file
View File

@@ -0,0 +1,2 @@
What's your name? Hello, hi!
0

BIN
test/hellosir.c0.ex Executable file

Binary file not shown.

1
test/iadd.c0.bc0out Normal file
View File

@@ -0,0 +1 @@
-2

1
test/iadd.c0.c0out Normal file
View File

@@ -0,0 +1 @@
-2

BIN
test/iadd.c0.ex Executable file

Binary file not shown.

3
test/ishr.c0 Normal file
View File

@@ -0,0 +1,3 @@
int main () {
return -1 >> 1; /* should return -1 */
}

24
test/ishr.c0.bc0 Normal file
View 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
View File

@@ -0,0 +1 @@
-1

1
test/ishr.c0.c0out Normal file
View File

@@ -0,0 +1 @@
-1

BIN
test/ishr.c0.ex Executable file

Binary file not shown.

10
test/isqrt.c0 Normal file
View 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
View 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
View File

1
test/isqrt.c0.c0out Normal file
View File

@@ -0,0 +1 @@
122

BIN
test/isqrt.c0.ex Executable file

Binary file not shown.

10
test/mid.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
155

1
test/mid.c0.c0out Normal file
View File

@@ -0,0 +1 @@
155

BIN
test/mid.c0.ex Executable file

Binary file not shown.

10
test/moreArrays.c0 Normal file
View 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
View 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

View File

@@ -0,0 +1 @@
23120

1
test/moreArrays.c0.c0out Normal file
View File

@@ -0,0 +1 @@
23120

BIN
test/moreArrays.c0.ex Executable file

Binary file not shown.

22
test/piazza1.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
18

1
test/piazza1.c0.c0out Normal file
View File

@@ -0,0 +1 @@
18

BIN
test/piazza1.c0.ex Executable file

Binary file not shown.

7
test/sample2.5.c0 Normal file
View 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
View 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
View File

0
test/sample2.5.c0.c0out Normal file
View File

BIN
test/sample2.5.c0.ex Executable file

Binary file not shown.

29
test/strings.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
hello there!?0

1
test/strings.c0.c0out Normal file
View File

@@ -0,0 +1 @@
hello there!?0

BIN
test/strings.c0.ex Executable file

Binary file not shown.

18
test/structs.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
potato chip1230

1
test/structs.c0.c0out Normal file
View File

@@ -0,0 +1 @@
potato chip1230

BIN
test/structs.c0.ex Executable file

Binary file not shown.

25
test/swapTest.c0.bc0 Normal file
View 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
View File

@@ -0,0 +1,7 @@
#use <conio>
int main() {
assert(2==2);
print("yolomode");
return 1;
}

40
test/testError.c0.bc0 Normal file
View 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
View File

@@ -0,0 +1 @@
yolomode1

1
test/testError.c0.c0out Normal file
View File

@@ -0,0 +1 @@
yolomode1

BIN
test/testError.c0.ex Executable file

Binary file not shown.

8
test/testif.c0 Normal file
View 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
View 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
View File

@@ -0,0 +1 @@
32

1
test/testif.c0.c0out Normal file
View File

@@ -0,0 +1 @@
32

BIN
test/testif.c0.ex Executable file

Binary file not shown.

135
test/tests.js Normal file
View 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