my blog lives here now
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

119 lines
3.1 KiB

let draw = SVG().addTo('#forth').size('100%', '100%')
let stack_element = (container, text) => {
let group = container.group()
group.add(
container.rect()
.size(100, 25)
.stroke('#000').fill('#ddd')
.attr('stroke-width', 2));
group.add(container.text(text).dmove((65 - text.length) / 2, -2));
console.log(group);
return group;
}
let the_code = [
[ 'push', 2 ],
[ 'push', 3 ],
[ 'push', 4 ],
[ 'mul' ],
[ 'add' ]
]
let the_stack = [], pc = 0, final = false;
let stack_container = draw.nested().move(draw.width() - '10%', 0)
let code_node = document.getElementById('code');
let push_val = (int) => {
let the_element =
stack_element(stack_container, int.toString()).move(10, 0);
the_element.animate(100, 0, 'now').move(10, 10);
the_stack.forEach(elem => elem.svg.animate(100, 0, 'now').dy(25));
the_stack.push({ svg: the_element, val: int });
}
let pop_val = () => {
let item = the_stack.pop()
item.svg.remove();
the_stack.forEach(elem => elem.svg.dy(-25));
return item.val;
}
let render_code = (code, pc) => {
while (code_node.firstChild) {
code_node.removeChild(code_node.firstChild);
}
let list = document.createElement('ul');
list.style = 'list-style-type: none;';
code.forEach((instruction, idx) => {
let i_type = instruction[0];
let li = document.createElement('li');
if (idx == pc) {
let cursor = document.createElement('span')
cursor.innerText = '> ';
cursor.classList.add('instruction-cursor');
li.appendChild(cursor);
}
let type_field = document.createElement('span');
type_field.innerText = i_type;
type_field.classList.add('instruction');
li.appendChild(type_field);
for (let i = 1; i < instruction.length; i++) {
li.append(' ');
let operand_field = document.createElement('span');
operand_field.innerText = instruction[i];
operand_field.classList.add('operand');
li.appendChild(operand_field);
}
list.appendChild(li);
});
code_node.appendChild(list);
};
let reset = () => {
the_stack.forEach(e => e.svg.remove());
the_stack = [];
pc = 0;
final = false;
document.getElementById('step').disabled = false;
render_code(the_code, 0);
}
let step = () => {
if (!final) {
const insn = the_code[pc++];
switch (insn[0]) {
case 'push':
push_val(insn[1]);
break;
case 'add':
if (the_stack.length < 2) {
console.error("machine error");
document.getElementById('step').disabled = true;
} else {
let x = pop_val(), y = pop_val();
push_val(x + y);
}
break;
case 'mul':
if (the_stack.length < 2) {
console.error("machine error");
document.getElementById('step').disabled = true;
} else {
let x = pop_val(), y = pop_val();
push_val(x * y);
}
break;
}
}
render_code(the_code, pc);
if (pc >= the_code.length) {
console.log("final state");
document.getElementById('step').disabled = true;
final = true;
}
}
render_code(the_code, pc);