Code for the littler Buttons the Computer used in the Turing Machine portion of the book.
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.
 
buttons-computer/src/routes/index.svelte

198 lines
5.3 KiB

<svelte:head>
<title>Buttons the Computer</title>
</svelte:head>
<script>
import {goto, stores} from '@sapper/app';
import { ButtonMachine } from 'buttons';
import Icon from '../components/Icon.svelte';
const { session } = stores();
let code = [
['PUSH', -10], // start at -10
['PUSH', 1], // increment by 1
['ADD'],
['JZ', 5], // if we're at 0 jumps to the end
['JUMP', 1] // the previous test fails so it jumps to loop again
];
let machine = new ButtonMachine(code);
let has_error = false;
$: has_error = machine.error != '';
const data_ops = new Set(['PUSH', 'JZ', 'JNZ', 'JUMP', 'STOR', 'RSTOR', 'HALT']);
const ops = ButtonMachine.operations();
const change_op = (i, count) => {
let cur_op = code[i][0];
let cur_index = ops.indexOf(cur_op);
let new_index = (cur_index + count) < 0 ? ops.length - 1 : (cur_index + count) % ops.length;
code[i][0] = ops[new_index];
}
const op_has_data = (op) => data_ops.has(op);
const run_machine = () => {
machine.run();
machine = machine; // make svelte go
}
const step_machine = () => {
machine.step();
machine = machine;
}
const reset_machine = () => {
machine = new ButtonMachine(code);
}
const clone_line = (i) => {
let clone = code[i];
code.splice(i, 0, [...clone]);
code = code;
}
const delete_line = (i) => {
let item = code.splice(i, 1);
code = code;
}
</script>
<style lang="scss">
@import "sass/_variables";
#status-panel {
font-size: 14px;
}
.active-line {
background-color: $green !important;
}
.empty-data {
width: 100%;
background-color: lighten($primary-color, 40%);
}
.off-canvas-toggle {
position: unset;
z-index: unset;
top: unset;
left: unset;
display: unset;
transition: unset;
padding: 5px;
}
</style>
<div class="container grid-lg" id="content" data-testid="buttons-page">
<div class="columns">
<div class="column col-4 col-sm-12 col-md-12 col-xs-12">
<a alt="Open/Close help sidebar" aria-label="Open/Close help sidebar" class="off-canvas-toggle btn btn-primary btn-action" href="#sidebar-id">
?¿
</a>
<button class="btn btn-primary" on:click={ run_machine }>
<Icon code="►" tooltip="Run it" tooltip_right={ true } light={ true }/>
</button>
<button class="btn btn-primary" on:click={ step_machine }>
<Icon code="→" tooltip="Step through" tooltip_right={ true } light={ true }/>
</button>
<button class="btn btn-primary" on:click={ reset_machine }>
<Icon code="■" tooltip="Reset" light={ true }/>
</button>
<div class="divider"></div>
{#each code as [op, data], i}
<div class="input-group">
{#if has_error && machine.error_line == i}
<Icon name="alert-triangle" color="red" />
{:else}
{i}:
{/if}
<button class:active-line={ machine.ip == i }
on:click={ () => change_op(i, +1) }
on:contextmenu|preventDefault={ () => change_op(i, -1) }
class="btn btn-primary input-group-btn">{op}</button>
{#if op_has_data(op)}
{#if op === 'STOR' || op === 'RSTOR' || op == 'HALT'}
<input class:active-line={ machine.ip == i }
type="text" class="form-input" placeholder="register" bind:value={data}>
{:else}
<input class:active-line={ machine.ip == i }
type="number" class="form-input" placeholder="data" bind:value={data}>
{/if}
{:else}
<div class:active-line={ machine.ip == i } class="empty-data"></div>
{/if}
<button class="btn btn-primary input-group-addon"
on:click={ () => clone_line(i) }>
<Icon name="copy" tooltip='Clone it'/>
</button>
<button class="btn btn-primary input-group-addon"
on:click={ () => delete_line(i) }>
<Icon name="delete" tooltip='Delete it'/>
</button>
</div>
{/each}
</div>
<div class="column col-8 col-sm-12 col-md-12 col-xs-12" id="status-panel">
<table class="table">
<thead>
<tr>
<th>IP</th>
<th>TICK</th>
<th>HALT</th>
<th>ERROR</th>
</tr>
</thead>
<tbody>
<tr class="active">
<td>{ machine.ip }</td>
<td>{ machine.tick }</td>
<td>{ machine.halted }</td>
<td>{ machine.error }</td>
</tr>
</tbody>
</table>
<table class="table"> <thead>
<tr>
<th>STACK</th>
</tr>
</thead>
{#each machine.stack as datum, i}
<tr>
<td>{datum}</td>
</tr>
{/each}
</table>
<table class="table">
<thead>
<tr>
<th>REGISTER</th>
<th>VALUE</th>
</tr>
</thead>
<tbody>
{#each machine.register_entries as [name, value] }
<tr class="active">
<td>{ name }</td>
<td>{ value }</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>