virtual machine reader for json language prototype
//bool comparison functions
var BoolFuncs = {
"==":function(a, b){
return a.value === b.value;
},
"!=":function(a, b){
return a.value !== b.value;
},
"<":function(a, b){
return a.value < b.value;
},
">":function(a, b){
return a.value > b.value;
},
"<=":function(a, b){
return a.value <= b.value;
},
">=":function(a, b){
return a.value >= b.value;
},
"&&":function(a, b){
return a.value && b.value;
},
"||":function(a, b){
return a.value || b.value;
}
};
//processes, or mini functions that facilitate operations
//dest is always the destination of where the resulting value is stored.
var procfuncs = {
//math funcs
"+":function(a, b, dest){
dest.value = a.value + b.value;
},
"-":function(a, b, dest){
dest.value = a.value - b.value;
},
"*":function(a, b, dest){
dest.value = a.value * b.value;
},
"/":function(a, b, dest){
dest.value = a.value / b.value;
},
"//":function(a, b, dest){
dest.value = Math.floor(a.value / b.value);
},
"%":function(a, b, dest){
dest.value = a.value % b.value;
},
"**":function(a, b, dest){
dest.value = Math.pow(a.value, b.value);
},
//concat oper, for strings or arrays
"+~":function(a, b, dest){
dest.value = a.concat(b);
},
//pushes or appends onto arrays
"push":function(a, b, dest){
a.value.push(b.value);
},
//pop operator only uses one operand, but needs both to be called
"pop":function(a, b, dest){
dest.value = a.value.pop();
},
//indexing operator
"get":function(a, b, dest){
dest.value = a.value[b.value];
},
//setitem oper for objects or arrays
"set":function(a, b, dest){
dest.value[a.value] = b.value;
},
//takes the length of a string or array
"len":function(a, b, dest){
dest.value = a.value.length;
},
//printing oper, must be called with a, b and dest
"print":function(a, b, dest){
console.log(a.value);
}
};
//class to implement variable collection and storage
var Vardict = (function(){
//private object to hold values in the dictionary
function Valobj(value){
this.value = value;
}
function Vardict(){
}
Vardict.prototype.init = function(key, value){
this[key] = new Valobj(value);
};
Vardict.prototype.del = function(key){
delete this[key];
};
Vardict.prototype.check = function(key){
return key in this;
};
//declares variable without assigning value
Vardict.prototype.declare = function(key){
this[key] = null;
};
//gets the entire value with it's object reference
//if key does not exist in object, creates a key that is null valued
Vardict.prototype.get = function(key){
if(this.check(key)){
return this[key];
}
else{
this.init(key, null);
return this[key];
}
};
//gets only the value associated with the reference
Vardict.prototype.getValue = function(key){
if(this.check(key)){
return this[key].value;
}
else{
return false;
}
};
//modifies the value of a preexisting object
Vardict.prototype.set = function(key, value){
if(this.check(key)){
this[key].value = value;
}
else {
return false;
}
};
return Vardict;
})();
//main class for virtual machine
var VirtualMachine = (function(){
//private object to hold values in the dictionary
function Valobj(value){
this.value = value;
}
function VirtualMachine(){
this.variables = new Vardict();
this.endstate = false;
this.comps = BoolFuncs;
this.procs = procfuncs;
this.beginstate = true;
}
//loads variables from a variable object, as a preprocessor arrangement
VirtualMachine.prototype.loadVars = function(obj){
for(var key in obj){
this.variables.init(key, obj[key]);
}
};
//method that turns values into value object for easy referencing.
VirtualMachine.prototype.setupVars = function(obj){
for(var key in obj){
//loads an object from memory if its already a variable
if(typeof obj[key] === 'string' && obj[key][0] === "@"){
obj[key] = this.variables.get(obj[key]);
}
//strings that don't start with @ will not be loaded
else if(key !== "op") {
obj[key] = new Valobj(obj[key]);
}
}
};
//evaluates one process
VirtualMachine.prototype.assembleProc = function(obj){
if("a" in obj && "b" in obj && "dest" in obj && "op"in obj){
this.procs[obj.op](obj.a, obj.b, obj.dest);
}
else{
throw "Process Error, invalid keys";
}
};
//evaluates if a condition object is true
VirtualMachine.prototype.assembleCond = function(obj){
if("a" in obj && "b" in obj && "op"in obj){
if(!(obj.op in this.comps)) throw "OPER ERROR";
return this.comps[obj.op](obj.a, obj.b);
}
};
//determines if an object is a block
VirtualMachine.prototype.isBlock = function(obj){
return "type" in obj && obj.type === "block" && "stmts" in obj;
};
//determines if an object is a conditional
VirtualMachine.prototype.isConditional = function(obj){
return "type" in obj && obj.type === "cond" && "exps" in obj && "t" in obj && "f" in obj;
};
//determines if an object is a loop statement
VirtualMachine.prototype.isLoop = function(obj){
return "type" in obj && obj.type === "loop" && "cond" in obj && "stmts" in obj;
};
VirtualMachine.prototype.isEnd = function(obj){
return "type" in obj && obj.type === "end";
};
return VirtualMachine;
})();
var a = new VirtualMachine();
//sample program object
var b = {
"vars":{
"@foo":4
},
"program":{
"type":"loop",
"cond":{
"op":">=",
"a":"@foo",
"b":10
},
"stmts":[
{
"op":"+",
"a":"@foo",
"b":1,
"dest":"@foo"
},
{
"op":"print",
"a":"@foo",
"b":"@foo",
"dest":"@foo"
}
],
"next":{
"type":"end"
}
}
};