diff options
author | Austin Adams <git@austinjadams.com> | 2020-05-31 15:42:02 -0700 |
---|---|---|
committer | Austin Adams <git@austinjadams.com> | 2020-05-31 15:42:02 -0700 |
commit | 0e8ee6496d2efa3b1dc9b1171b9e0cfd663dc74a (patch) | |
tree | 1fa81ff57ba22c86bc50863b67787806d27078bb /packages/novice-web/novice-web/components/GuiDebugger.tsx | |
parent | 96dfefba92f6ed46131593bacd49a99186b0a3fd (diff) | |
download | novice-0e8ee6496d2efa3b1dc9b1171b9e0cfd663dc74a.tar.gz novice-0e8ee6496d2efa3b1dc9b1171b9e0cfd663dc74a.tar.xz |
Create worker for assembler, add debug buttons
Diffstat (limited to 'packages/novice-web/novice-web/components/GuiDebugger.tsx')
-rw-r--r-- | packages/novice-web/novice-web/components/GuiDebugger.tsx | 122 |
1 files changed, 99 insertions, 23 deletions
diff --git a/packages/novice-web/novice-web/components/GuiDebugger.tsx b/packages/novice-web/novice-web/components/GuiDebugger.tsx index f0e6fb3..9894281 100644 --- a/packages/novice-web/novice-web/components/GuiDebugger.tsx +++ b/packages/novice-web/novice-web/components/GuiDebugger.tsx @@ -1,11 +1,15 @@ import { FullMachineState, getIsa, Isa, fmtHex, Symbols, BaseSymbols } from 'novice'; import * as React from 'react'; import { VariableSizeGrid as Grid } from 'react-window'; -import { FrontendMessage, WorkerMessage } from '../worker/proto'; +import { AssemblerFrontendMessage, AssemblerWorkerMessage } from '../workers/assembler'; +import { DebuggerFrontendMessage, DebuggerWorkerMessage } from '../workers/debugger'; +import { AssembleForm } from './AssembleForm'; export interface GuiDebuggerProps { - workerBundleUrl: string; + debuggerWorkerBundleUrl: string; + assemblerWorkerBundleUrl: string; isaName: string; + initialAssemblyCode: string; } export interface GuiDebuggerState { @@ -16,7 +20,8 @@ export class GuiDebugger extends React.Component<GuiDebuggerProps, GuiDebuggerState> { private isa: Isa; private symbols: Symbols; - private worker: Worker; + private debuggerWorker: Worker; + private assemblerWorker: Worker; constructor(props: GuiDebuggerProps) { super(props); @@ -27,10 +32,20 @@ export class GuiDebugger extends React.Component<GuiDebuggerProps, state: this.isa.initMachineState(), }; - (this.worker = new Worker(this.props.workerBundleUrl)).onerror = - this.onError.bind(this); - this.worker.onmessage = this.onMessage.bind(this); - this.postMessage({ kind: 'reset', isa: this.props.isaName }); + this.onError = this.onError.bind(this); + this.onDebuggerMessage = this.onDebuggerMessage.bind(this); + this.onAssemblerMessage = this.onAssemblerMessage.bind(this); + this.handleAssembleRequest = this.handleAssembleRequest.bind(this); + this.handleStepRequest = this.handleStepRequest.bind(this); + this.handleUnstepRequest = this.handleUnstepRequest.bind(this); + this.handleContinueRequest = this.handleContinueRequest.bind(this); + + this.debuggerWorker = this.loadWorkerBundle(this.props.debuggerWorkerBundleUrl, + this.onDebuggerMessage); + this.assemblerWorker = this.loadWorkerBundle(this.props.assemblerWorkerBundleUrl, + this.onAssemblerMessage); + + this.postDebuggerMessage({ kind: 'reset', isa: this.props.isaName }); } public componentDidUpdate(prevProps: GuiDebuggerProps) { @@ -38,17 +53,15 @@ export class GuiDebugger extends React.Component<GuiDebuggerProps, if (prevProps.isaName !== this.props.isaName) { this.isa = getIsa(this.props.isaName); this.setState({ state: this.isa.initMachineState() }); - this.postMessage({ kind: 'reset', isa: this.props.isaName }); + this.postDebuggerMessage({ kind: 'reset', isa: this.props.isaName }); } } - public onError(err: ErrorEvent) { + private onError(err: ErrorEvent) { console.log(err); } - public onMessage(event: MessageEvent) { - const msg: WorkerMessage = event.data; - + private onDebuggerMessage(msg: DebuggerWorkerMessage) { switch (msg.kind) { case 'updates': const [state, _] = this.isa.stateApplyUpdates( @@ -66,9 +79,28 @@ export class GuiDebugger extends React.Component<GuiDebuggerProps, } } + private onAssemblerMessage(msg: AssemblerWorkerMessage) { + switch (msg.kind) { + case 'assembly-finished': + const sections = msg.sections; + this.postDebuggerMessage({ kind: 'load-sections', sections }); + break; + + case 'assembly-error': + const errorMessage = msg.errorMessage; + console.error('assembly error in frontend', errorMessage); + break; + + default: + const __: never = msg; + } + } + public render() { - const cols = [80, 80, 80, 200]; + const rowHeight = 20; + const cols = [20, 80, 80, 80, 200]; const colVal: ((addr: number) => string)[] = [ + addr => (this.state.state.pc == addr)? '►' : '', addr => this.fmtAddr(addr), addr => this.fmtWord(this.isa.stateLoad(this.state.state, addr)), addr => this.isa.stateLoad(this.state.state, addr).toString(10), @@ -84,18 +116,62 @@ export class GuiDebugger extends React.Component<GuiDebuggerProps, </div> ); - return (<Grid - columnCount={cols.length} - columnWidth={i => cols[i]} - rowCount={Math.pow(2, this.isa.spec.mem.space)} - rowHeight={i => 20} - width={cols.reduce((acc, cur) => acc + cur) + 32} - height={600} - >{cell}</Grid>); + return ( + <div className='gui-wrapper'> + <div className='memory-view'> + <Grid columnCount={cols.length} + columnWidth={i => cols[i]} + rowCount={Math.pow(2, this.isa.spec.mem.space)} + rowHeight={i => rowHeight} + width={cols.reduce((acc, cur) => acc + cur) + 32} + height={600} + initialScrollTop={this.state.state.pc * rowHeight}>{cell}</Grid> + </div> + <AssembleForm initialAssemblyCode={this.props.initialAssemblyCode} + handleAssembleRequest={this.handleAssembleRequest} + handleStepRequest={this.handleStepRequest} + handleUnstepRequest={this.handleUnstepRequest} + handleContinueRequest={this.handleContinueRequest} /> + </div> + ); + } + + private loadWorkerBundle<WorkerMessageType>(workerBundleUrl: string, + onMessage: (msg: WorkerMessageType) => void): Worker { + const worker = new Worker(workerBundleUrl); + worker.onerror = this.onError; + worker.onmessage = (e: MessageEvent) => { + const msg: WorkerMessageType = e.data; + onMessage(msg); + }; + return worker; + } + + private postDebuggerMessage(msg: DebuggerFrontendMessage): void { + this.debuggerWorker.postMessage(msg); + } + + private postAssemblerMessage(msg: AssemblerFrontendMessage): void { + this.assemblerWorker.postMessage(msg); + } + + private handleAssembleRequest(assemblyCode: string): void { + // TODO: it's a hack to assume isa name == assembler config name + this.postAssemblerMessage({ kind: 'assemble', + configName: this.props.isaName, + assemblyCode }); + } + + private handleStepRequest(): void { + this.postDebuggerMessage({ kind: 'step' }); + } + + private handleUnstepRequest(): void { + this.postDebuggerMessage({ kind: 'unstep' }); } - private postMessage(msg: FrontendMessage): void { - this.worker.postMessage(msg); + private handleContinueRequest(): void { + this.postDebuggerMessage({ kind: 'run' }); } private fmtAddr(addr: number): string { |