microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
minestarks/circuit-magic

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/npm/qsharp/src/debug-service/debug-service.ts

208lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import {
5 CURRENT_VERSION,
6 type CircuitGroup as CircuitData,
7} from "../data-structures/circuit.js";
8import type {
9 DebugService,
10 IBreakpointSpan,
11 IQuantumState,
12 IStackFrame,
13 IStructStepResult,
14 IVariable,
15} from "../../lib/web/qsc_wasm.js";
16import { ProgramConfig } from "../browser.js";
17import { eventStringToMsg } from "../compiler/common.js";
18import {
19 IQscEventTarget,
20 QscEventData,
21 QscEvents,
22 makeEvent,
23} from "../compiler/events.js";
24import { log } from "../log.js";
25import { IServiceProxy, ServiceProtocol } from "../workers/common.js";
26import { toWasmProgramConfig } from "../compiler/compiler.js";
27
28type QscWasm = typeof import("../../lib/web/qsc_wasm.js");
29
30// These need to be async/promise results for when communicating across a WebWorker, however
31// for running the debugger in the same thread the result will be synchronous (a resolved promise).
32export interface IDebugService {
33 loadProgram(
34 program: ProgramConfig,
35 entry: string | undefined,
36 ): Promise<string>;
37 getBreakpoints(path: string): Promise<IBreakpointSpan[]>;
38 getLocalVariables(frameID: number): Promise<Array<IVariable>>;
39 captureQuantumState(): Promise<Array<IQuantumState>>;
40 getCircuit(): Promise<CircuitData>;
41 getStackFrames(): Promise<IStackFrame[]>;
42 evalContinue(
43 bps: number[],
44 eventHandler: IQscEventTarget,
45 ): Promise<IStructStepResult>;
46 evalNext(
47 bps: number[],
48 eventHandler: IQscEventTarget,
49 ): Promise<IStructStepResult>;
50 evalStepIn(
51 bps: number[],
52 eventHandler: IQscEventTarget,
53 ): Promise<IStructStepResult>;
54 evalStepOut(
55 bps: number[],
56 eventHandler: IQscEventTarget,
57 ): Promise<IStructStepResult>;
58 dispose(): Promise<void>;
59}
60
61export type IDebugServiceWorker = IDebugService & IServiceProxy;
62
63export class QSharpDebugService implements IDebugService {
64 private wasm: QscWasm;
65 private debugService: DebugService;
66
67 constructor(wasm: QscWasm) {
68 log.info("Constructing a QSharpDebugService instance");
69 this.wasm = wasm;
70 this.debugService = new wasm.DebugService();
71 }
72
73 async loadProgram(
74 program: ProgramConfig,
75 entry: string | undefined,
76 ): Promise<string> {
77 return this.debugService.load_program(
78 toWasmProgramConfig(program, "unrestricted"),
79 entry,
80 );
81 }
82
83 async getBreakpoints(path: string): Promise<IBreakpointSpan[]> {
84 return this.debugService.get_breakpoints(path).spans;
85 }
86
87 async getLocalVariables(frameID: number): Promise<Array<IVariable>> {
88 const variable_list = this.debugService.get_locals(frameID);
89 return variable_list.variables;
90 }
91
92 async captureQuantumState(): Promise<Array<IQuantumState>> {
93 const state = this.debugService.capture_quantum_state();
94 return state.entries;
95 }
96
97 async getCircuit(): Promise<CircuitData> {
98 const circuit = this.debugService.get_circuit();
99 return {
100 circuits: [circuit],
101 version: CURRENT_VERSION,
102 };
103 }
104
105 async getStackFrames(): Promise<IStackFrame[]> {
106 return this.debugService.get_stack_frames().frames;
107 }
108
109 async evalContinue(
110 bps: number[],
111 eventHandler: IQscEventTarget,
112 ): Promise<IStructStepResult> {
113 const event_cb = (msg: string) => onCompilerEvent(msg, eventHandler);
114 const ids = new Uint32Array(bps);
115 return this.debugService.eval_continue(event_cb, ids);
116 }
117
118 async evalNext(
119 bps: number[],
120 eventHandler: IQscEventTarget,
121 ): Promise<IStructStepResult> {
122 const event_cb = (msg: string) => onCompilerEvent(msg, eventHandler);
123 const ids = new Uint32Array(bps);
124 return this.debugService.eval_next(event_cb, ids);
125 }
126
127 async evalStepIn(
128 bps: number[],
129 eventHandler: IQscEventTarget,
130 ): Promise<IStructStepResult> {
131 const event_cb = (msg: string) => onCompilerEvent(msg, eventHandler);
132 const ids = new Uint32Array(bps);
133 return this.debugService.eval_step_in(event_cb, ids);
134 }
135
136 async evalStepOut(
137 bps: number[],
138 eventHandler: IQscEventTarget,
139 ): Promise<IStructStepResult> {
140 const event_cb = (msg: string) => onCompilerEvent(msg, eventHandler);
141 const ids = new Uint32Array(bps);
142 return this.debugService.eval_step_out(event_cb, ids);
143 }
144
145 async dispose() {
146 this.debugService.free();
147 }
148}
149
150export function onCompilerEvent(msg: string, eventTarget: IQscEventTarget) {
151 const qscMsg = eventStringToMsg(msg);
152 if (!qscMsg) {
153 log.error("Unknown event message: %s", msg);
154 return;
155 }
156
157 let qscEvent: QscEvents;
158
159 const msgType = qscMsg.type;
160 switch (msgType) {
161 case "Message":
162 qscEvent = makeEvent("Message", qscMsg.message);
163 break;
164 case "DumpMachine":
165 qscEvent = makeEvent("DumpMachine", {
166 state: qscMsg.state,
167 stateLatex: qscMsg.stateLatex,
168 qubitCount: qscMsg.qubitCount,
169 });
170 break;
171 case "Result":
172 qscEvent = makeEvent("Result", qscMsg.result);
173 break;
174 case "Matrix":
175 qscEvent = makeEvent("Matrix", {
176 matrix: qscMsg.matrix,
177 matrixLatex: qscMsg.matrixLatex,
178 });
179 break;
180 default:
181 log.never(msgType);
182 throw "Unexpected message type";
183 }
184 log.debug("worker dispatching event " + JSON.stringify(qscEvent));
185 eventTarget.dispatchEvent(qscEvent);
186}
187
188/** The protocol definition to allow running the debugger in a worker. */
189export const debugServiceProtocol: ServiceProtocol<
190 IDebugService,
191 QscEventData
192> = {
193 class: QSharpDebugService,
194 methods: {
195 loadProgram: "request",
196 getBreakpoints: "request",
197 getLocalVariables: "request",
198 captureQuantumState: "request",
199 getCircuit: "request",
200 getStackFrames: "request",
201 evalContinue: "requestWithProgress",
202 evalNext: "requestWithProgress",
203 evalStepIn: "requestWithProgress",
204 evalStepOut: "requestWithProgress",
205 dispose: "request",
206 },
207 eventNames: ["DumpMachine", "Message", "Matrix", "Result"],
208};
209