/src/components/App.js

https://gitlab.com/bxt/brainfuck-debugger · JavaScript · 117 lines · 102 code · 15 blank · 0 comment · 1 complexity · 08a74dad61a5a3e25a525c871f4c153d MD5 · raw file

  1. import React from 'react'
  2. import Box from './Box'
  3. import Button from './Button'
  4. import CodeEditor from './CodeEditor'
  5. import CodeViewer from './CodeViewer'
  6. import Extra from './Extra'
  7. import InputEditor from './InputEditor'
  8. import InputViewer from './InputViewer'
  9. import MemoryViewer from './MemoryViewer'
  10. import OutputViewer from './OutputViewer'
  11. import Player from './Player'
  12. import Step from './Step'
  13. import { isDone, restart, run, step } from '../brainfuck'
  14. import type { Machine } from '../brainfuck'
  15. import sampleProgram from '../sampleProgram'
  16. export default class App extends React.Component {
  17. state = {
  18. input: `!dlroW olleH\nstep on no pets\nfoo\n`,
  19. inputPointer: 0,
  20. instructionPointer: 0,
  21. instructions: sampleProgram,
  22. memory: [0],
  23. memoryPointer: 0,
  24. output: '',
  25. running: false,
  26. }
  27. modifyMachineState(f: Machine => void) {
  28. this.setState((oldState) => {
  29. let {running, ...machine} = oldState
  30. void running // unused var bug in linter
  31. f(machine)
  32. return {running: !isDone(machine), ...machine}
  33. })
  34. }
  35. handleInputChange = (value: string) => {
  36. this.setState({input: value})
  37. }
  38. handleInstructionsChange = (value: string) => {
  39. this.setState({instructions: value})
  40. }
  41. start = () => {
  42. this.modifyMachineState(restart)
  43. }
  44. step = (n: number) => {
  45. this.modifyMachineState(machine => {
  46. for (let i = 0; i < n; i++) step(machine)
  47. })
  48. }
  49. finish = () => {
  50. this.modifyMachineState((m) => { run(m) })
  51. }
  52. abort = () => {
  53. this.setState({running: false})
  54. }
  55. render() {
  56. const {
  57. input,
  58. inputPointer,
  59. instructionPointer,
  60. instructions,
  61. memory,
  62. memoryPointer,
  63. output,
  64. running,
  65. } = this.state
  66. const instructionPane = running
  67. ? (
  68. <Box>
  69. <Button onClick={this.finish}>finish</Button>
  70. <Step onStep={this.step} />
  71. <Player onTick={() => this.step(1)} />
  72. <Button onClick={this.abort}>abort</Button>
  73. <CodeViewer {...{instructionPointer, instructions}} />
  74. </Box>
  75. )
  76. : (
  77. <Box>
  78. <Button onClick={this.start}>start</Button>
  79. <CodeEditor {...{instructions}} onChange={this.handleInstructionsChange} />
  80. </Box>
  81. )
  82. const inputPane = running
  83. ? <InputViewer {...{input, inputPointer}} />
  84. : <InputEditor {...{input}} onChange={this.handleInputChange}/>
  85. return (
  86. <div>
  87. {instructionPane}
  88. <Box>
  89. <MemoryViewer {...{memory, memoryPointer}} />
  90. </Box>
  91. <Box>
  92. {inputPane}
  93. </Box>
  94. <Box>
  95. <OutputViewer {...{output}} />
  96. </Box>
  97. <br style={{clear: 'left'}} />
  98. <Extra {...{instructions}} />
  99. </div>
  100. )
  101. }
  102. }