|
|
- 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);
|