Assembler interpreter (part II)
This commit is contained in:
62
assembler-interpreter-part-ii/index.js
Normal file
62
assembler-interpreter-part-ii/index.js
Normal file
@@ -0,0 +1,62 @@
|
||||
// https://www.codewars.com/kata/58e61f3d8ff24f774400002c/javascript
|
||||
|
||||
function assemblerInterpreter(program) {
|
||||
const lines = (program
|
||||
.split(/\n/)
|
||||
.map(line => line.replace(/;.*$/, '').trim())
|
||||
.filter(line => line !== ''));
|
||||
const parsed = [];
|
||||
const labels = new Map();
|
||||
let diff = 0;
|
||||
for (i = 0; i < lines.length; ++i) {
|
||||
const tokens = lines[i].split(/[,\s]+/);
|
||||
const m = tokens[0].match(/(\w+)\:/);
|
||||
if (m) {
|
||||
labels.set(m[1], i-diff);
|
||||
++diff;
|
||||
} else if (tokens[0] === 'msg') {
|
||||
parsed[i-diff] = lines[i].match(/('[^']*')|[a-z0-9_]+/g);
|
||||
} else {
|
||||
parsed[i-diff] = tokens;
|
||||
}
|
||||
}
|
||||
let ip = 0;
|
||||
let cmp;
|
||||
const res = [];
|
||||
const stack = [];
|
||||
const regs = new Map();
|
||||
const constOrVal = n => ((+n) + '') === n ? +n : regs.get(n);
|
||||
const jmpIf = (lbl, cond) => ip = cond ? labels.get(lbl) - 1 : ip;
|
||||
const instr = {
|
||||
mov: (a, b) => regs.set(a, constOrVal(b)),
|
||||
inc: a => regs.set(a, regs.get(a) + 1),
|
||||
dec: a => regs.set(a, regs.get(a) - 1),
|
||||
add: (a, b) => regs.set(a, regs.get(a) + constOrVal(b)),
|
||||
sub: (a, b) => regs.set(a, regs.get(a) - constOrVal(b)),
|
||||
mul: (a, b) => regs.set(a, regs.get(a) * constOrVal(b)),
|
||||
div: (a, b) => regs.set(a, regs.get(a) / constOrVal(b) | 0),
|
||||
jmp: lbl => jmpIf(lbl, true),
|
||||
cmp: (a, b) => cmp = Math.sign(constOrVal(a) - constOrVal(b)),
|
||||
jne: lbl => jmpIf(lbl, cmp !== 0),
|
||||
je: lbl => jmpIf(lbl, cmp === 0),
|
||||
jge: lbl => jmpIf(lbl, cmp >= 0),
|
||||
jg: lbl => jmpIf(lbl, cmp > 0),
|
||||
jle: lbl => jmpIf(lbl, cmp <= 0),
|
||||
jl: lbl => jmpIf(lbl, cmp < 0),
|
||||
call: lbl => (stack.push(ip), jmpIf(lbl, true)),
|
||||
ret: () => ip = stack.pop(),
|
||||
msg: (...args) => res.push(args.map(arg => {
|
||||
const m = arg.match(/^'(.*)'$/);
|
||||
if (m) return m[1];
|
||||
return constOrVal(arg);
|
||||
}).join``)
|
||||
};
|
||||
let cntdwn = 1e6;
|
||||
while (ip < parsed.length && --cntdwn > 0) {
|
||||
const [cmd, ...args] = parsed[ip];
|
||||
if (cmd === 'end') return res.join``;
|
||||
instr[cmd](...args);
|
||||
++ip;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user