microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
amcasey/i2d

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

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