Created
November 25, 2015 10:57
-
-
Save mouseroot/a7fbd4943353856f42a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Very simple jump on 9 to next op | |
/* | |
var program = ["0","0","0","1337","9","4"]; | |
var pc = 0; | |
for(var i=0;i < program.length;i++) { | |
switch(program[i]) | |
{ | |
case "0": | |
//Skip | |
break; | |
case "9": | |
i = parseInt(program[i + 1]); | |
i++; | |
break; | |
default: | |
//Skip | |
console.log("Default:",program[i]); | |
break; | |
} | |
pc = i; | |
} | |
*/ | |
//Example | |
/* | |
var _program = [ | |
"set","s","something", | |
".func","myFunc", | |
"set","s","something_else", | |
"ret", | |
".func","someOtherFunc", | |
"set","s","never_exec_me", | |
"ret", | |
".invoke","myFunc", | |
".invoke","someOtherFunc" | |
]; | |
var program = [ | |
"func","apples", | |
"set","a","Apples", | |
"ret", | |
"endfunc", | |
"func","bread", | |
"set","b","Bread", | |
"ret", | |
"endfunc", | |
"func","main", | |
"invoke","apples", | |
"invoke","bread", | |
"ret", | |
"endfunc", | |
"set","s","starting main...", | |
"invoke","main" | |
]; | |
*/ | |
function searchLabel(program,labelName) { | |
var loc = program.indexOf(":" + labelName,0); | |
if(loc > -1) { | |
return loc; | |
} | |
else { | |
return null; | |
} | |
} | |
function executeFunctionByName(str, args) { | |
var arr = str.split('.'); | |
var fn = window[ arr[0] ]; | |
for (var i = 1; i < arr.length; i++) | |
{ | |
fn = fn[ arr[i] ]; | |
} | |
fn.apply(window, args); | |
} | |
var slot_api = { | |
set: function(i, tables, program) { | |
var slot = program[i + 1].toUpperCase(); | |
var value = program[i + 2]; | |
if(slot in tables.registers) { | |
tables.registers[slot] = value; | |
} | |
i += 2; | |
}, | |
sets: function(i, tables, program) { | |
var name_dst = program[i + 1].toUpperCase(); | |
var name_src = program[i + 2].toUpperCase(); | |
if(name_dst in tables.registers && name_src in tables.registers) { | |
var val = tables.registers[name_src]; | |
tables.registers[name_dst] = val; | |
} | |
i += 2; | |
}, | |
incs: function(i, tables, program) { | |
var name = program[i + 1].toUpperCase(); | |
if(name in tables.registers) { | |
tables.registers[name] = parseInt(tables.registers[name]) + 1; | |
} | |
i += 1; | |
}, | |
decs: function(i, tables, program) { | |
var name = program[i + 1].toUpperCase(); | |
if(name in tables.registers) { | |
tables.registers[name] = parseInt(tables.registers[name]) - 1; | |
} | |
i += 1; | |
}, | |
push: function(i, tables, stack, program) { | |
var value = program[i + 1]; | |
stack.push(value); | |
i += 1; | |
}, | |
pushs: function(i, tables, stack, program) { | |
var reg = program[i + 1].toUpperCase(); | |
if(reg in tables.registers) { | |
var value = tables.registers[reg]; | |
stack.push(value); | |
} | |
i += 1; | |
}, | |
pops: function(i, tables, stack, program) { | |
var reg = program[i + 1].toUpperCase(); | |
if(reg in tables.registers) { | |
tables.registers[reg] = stack.pop(); | |
} | |
i += 1; | |
}, | |
cmps: function(i, tables, program) { | |
var opA = program[i + 1].toUpperCase(); | |
var opB = program[i + 2].toUpperCase(); | |
if(opA in tables.registers && opB in tables.registers) { | |
var valA = tables.registers[opA]; | |
var valB = tables.registers[opB]; | |
if(valA == valB) { | |
tables.registers["F"] = 1; | |
} | |
else { | |
tables.registers["F"] = 0; | |
} | |
} | |
i += 2; | |
}, | |
je: function(i, tables, program) { | |
var dest = program[i + 1]; | |
if(tables.registers["F"] == 1) { | |
if(result = searchLabel(program,dest)) { | |
i = result; | |
} | |
} | |
else { | |
i += 1; | |
} | |
}, | |
jne: function(i, tables, program) { | |
var dest = program[i + 1]; | |
if(tables.registers["F"] == 0) { | |
if(result = searchLabel(program, dest)) { | |
i = result; | |
} | |
} | |
else { | |
i += 1; | |
} | |
}, | |
loop: function(i, tables, stack, program) { | |
var count = parseInt(program[i + 1]); | |
if(program[i + 1].toUpperCase() in tables.registers) { | |
var reg = program[i + 1].toUpperCase(); | |
count = parseInt(tables.registers[reg]); | |
//console.log("Count from register:",count); | |
} | |
else { | |
//console.log("Count from param"); | |
} | |
stack.push(i + 1); | |
loop_max = count; | |
loop_counter = 0; | |
i += 1; | |
}, | |
endloop: function(i, tables, stack, program) { | |
loop_counter += 1; | |
if(loop_counter == loop_max) { | |
//console.log("Last loop"); | |
//console.log("Loop counter:",loop_counter); | |
stack.pop(); | |
} | |
else { | |
//console.log("Still inside loop"); | |
//console.log("Loop counter:",loop_counter); | |
var stackPop = stack[stack.length - 1]; | |
i = stackPop; | |
//Skip for now | |
} | |
}, | |
nop: function(i, tables, program) { | |
}, | |
adds: function(i, tables, program) { | |
var addend = program[i + 1].toUpperCase(); | |
var opperand = program[i + 2].toUpperCase(); | |
if(addend in tables.registers && opperand in tables.registers) { | |
var valA = parseInt(tables.registers[addend]); | |
var valB = parseInt(tables.registers[opperand]); | |
tables.registers["D"] = valA + valB; | |
} | |
i += 2; | |
}, | |
subs: function(i, tables, program) { | |
var subend = program[i + 1].toUpperCase(); | |
var opperand = program[i + 2].toUpperCase(); | |
if(subend in tables.registers && opperand in tables.registers) { | |
var valA = parseInt(tables.registers[subend]); | |
var valB = parseInt(tables.registers[opperand]); | |
tables.registers["D"] = valA - valB; | |
} | |
i += 2; | |
}, | |
in: function(i, tables, program) { | |
var dest = program[i + 1].toUpperCase(); | |
var input_source = program[i + 2]; | |
var input_val = document.querySelector(input_source).value; | |
if(dest in tables.registers) { | |
tables.registers[dest] = input_val; | |
} | |
i += 2; | |
}, | |
out: function(i, tables, program) { | |
var source = program[i + 1].toUpperCase(); | |
var output_source = program[i + 2]; | |
if(source in tables.registers) { | |
var val = tables.registers[source]; | |
document.querySelector(output_source).value = val; | |
} | |
i += 2; | |
}, | |
func: function(i, tables, program) { | |
var function_name = program[i + 1]; | |
tables.functions[function_name] = i; | |
var end_func = program.indexOf("endfunc",i); | |
//var _tmp = program; | |
//var func_splice = _tmp.slice(i + 2,end_func); | |
//console.log("Function:",function_name,end_func,func_splice); | |
i = end_func; | |
}, | |
ret: function(i, tables, stack, program) { | |
if(exec_flag) { | |
var ret = stack.pop(); | |
if(stack.length > 0) { | |
//console.log("Returning to:",program[ret],ret); | |
exec_flag = true; | |
} else { | |
//console.log("No longer in any function:",stack); | |
exec_flag = false; | |
} | |
i = ret; | |
} | |
}, | |
invoke: function(i, tables, stack, program) { | |
var function_name = program[i + 1]; | |
//console.log("Pushing Iter (Return Point):",i,program[i]); | |
stack.push(i); | |
exec_flag = true; | |
//Lookup lands on the func decleration | |
var lookup = tables.functions[function_name]; | |
//console.log("Invoking:",function_name,"Going to:",lookup,program[lookup]); | |
i = lookup; | |
}, | |
call: function(i, tables, program) { | |
var func = program[i + 1]; | |
executeFunctionByName(func,stack); | |
i += 1; | |
}, | |
eval: function(i, tables, program) { | |
var prog = program[i + 1]; | |
prog = prog.trim().replace(new RegExp('/',"g"), ','); | |
console.log(prog); | |
eval(prog); | |
i += 1; | |
}, | |
reset: function(i, tables, program) { | |
var temp_i = i; | |
tables.registers = { | |
A: 0, | |
B: 0, | |
C: 0, | |
D: 0, | |
E: "ERRORSTR", | |
F: 0, | |
I: temp_i, | |
S: "SLOTSTR", | |
SP: 0 | |
}; | |
loop_counter = 0; | |
loop_max = 0; | |
exec_flag = false; | |
stack = []; | |
tables.functions = {}; | |
}, | |
jmp: function(i, tables, program) { | |
var dest = program[i + 1]; | |
//Search for it | |
if(result = searchLabel(program, dest)) { | |
i = result; | |
} | |
} | |
} | |
function slot_step(tables, stack, i, program) { | |
switch(program[i]) { | |
case "set": | |
slot_api.set(i, tables, program); | |
break; | |
case "sets": | |
slot_api.sets(i, tables, program); | |
break; | |
case "incs": | |
slot_api.incs(i, tables, program); | |
break; | |
case "decs": | |
slot_api.decs(i, tables, program); | |
break; | |
case "push": | |
slot_api.push(i, tables, stack, program); | |
break; | |
case "pushs": | |
slot_api.pushs(i, tables, stack, program); | |
break; | |
case "pops": | |
slot_api.pops(i, tables, stack, program); | |
break; | |
case "cmps": | |
slot_api.cmps(i, tables, program); | |
break; | |
case "je": | |
slot_api.je(i, tables, program); | |
break; | |
case "jne": | |
slot_api.jne(i, tables, program); | |
break; | |
case "loop": | |
slot_api.loop(i, tables, stack, program); | |
break; | |
case "endloop": | |
slot_api.endloop(i, tables, stack, program); | |
break; | |
case "nop": | |
slot_api.nop(i, tables, program); | |
break; | |
case "adds": | |
slot_api.adds(i, tables, program); | |
break; | |
case "subs": | |
slot_api.subs(i, tables, program); | |
break; | |
case "in": | |
slot_api.in(i, tables, program); | |
break; | |
case "out": | |
slot_api.out(i, tables, program); | |
break; | |
case ".eval": | |
slot_api.eval(i, tables, program); | |
break; | |
case ".com": | |
//Skip comments | |
i += 1; | |
break; | |
case ".device": | |
var device = program[i + 1]; | |
var handle = program[i + 2]; | |
tables.devices[device] = document.querySelector(handle).getContext("2d"); | |
i += 2; | |
break; | |
case ".reset": | |
slot_api.reset(i, tables, program); | |
break; | |
case "func": | |
slot_api.func(i, tables, program); | |
break; | |
case "invoke": | |
slot_api.invoke(i, tables, stack, program); | |
break; | |
case "call": | |
slot_api.call(i, tables, stack, program); | |
break; | |
case "ret": | |
slot_api.ret(i, tables, stack, program); | |
break; | |
case "jmp": | |
slot_api.jmp(i, tables, program); | |
break; | |
case ".debug": | |
console.log("SlotVM DEBUG:",tables,stack); | |
break; | |
case ".video": | |
var attr = program[i + 1]; | |
var value = program[i + 2]; | |
tables.devices.video[attr] = value; | |
i += 2; | |
break; | |
default: | |
//console.log("Skipping:",program[i]); | |
//Skip | |
break; | |
} | |
} | |
function slot_run(savestate, program) { | |
var exec_flag = false; | |
var loop_counter = 0; | |
var stack = []; | |
var tables = { | |
functions: {}, | |
devices: {}, | |
registers: { | |
A: 0, | |
B: 0, | |
C: 0, | |
D: 0, | |
E: "NOERROR", | |
F: 0, | |
I: 0, | |
S: "SLOTSTR", | |
SP: 0 | |
} | |
} | |
if(savestate) { | |
tables = savestate; | |
} | |
for(var i=0;i < program.length;i++) { | |
slot_step(tables, stack, i, program); | |
} | |
} | |
window.slot_step = slot_step; | |
window.slot_run = slot_run; | |
window.slot_api = slot_api; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment