Skip to content

Commit b467eac

Browse files
committed
Add diagnostic support to Query Interval.
1 parent 0b2e029 commit b467eac

File tree

4 files changed

+73
-23
lines changed

4 files changed

+73
-23
lines changed

src/debug/observer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export class Observer {
8787
this.reference = this.session.bindReference(this.referenceName, unboundReference);
8888
}
8989
const reference = this.reference; // could get invalidated during `await` below
90-
const sample = await this.session.queryAtCursor(reference);
90+
const sample = await this.session.queryAtCursor({ reference });
9191
for (const [designation, handle] of reference.allHandles()) {
9292
const observable = this.observables.get(designation.canonicalKey)!;
9393
observable.update(sample.extract(handle));

src/debug/session.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import * as proto from '../cxxrtl/proto';
44
import { ILink } from '../cxxrtl/link';
55
import { Connection } from '../cxxrtl/client';
66
import { TimeInterval, TimePoint } from '../model/time';
7-
import { Reference, Sample, UnboundReference } from '../model/sample';
7+
import { Diagnostic, Reference, Sample, UnboundReference } from '../model/sample';
88
import { Variable } from '../model/variable';
99
import { Scope } from '../model/scope';
1010
import { Location } from '../model/source';
1111

1212
function lazy<T>(thunk: () => Thenable<T>): Thenable<T> {
1313
return { then: (onfulfilled, onrejected) => thunk().then(onfulfilled, onrejected) };
1414
}
15+
1516
function matchLocation(location: Location, filename: string, position: vscode.Position) {
1617
if (location.file !== filename) {
1718
return false;
@@ -214,38 +215,55 @@ export class Session {
214215
}
215216

216217
async queryInterval(
217-
reference: Reference,
218218
interval: TimeInterval,
219-
options: { collapse?: boolean } = {}
219+
options: {
220+
reference?: Reference,
221+
diagnostics?: boolean
222+
collapse?: boolean,
223+
} = {}
220224
): Promise<Sample[]> {
221-
this.checkReferenceEpoch(reference.name, reference.epoch);
225+
const reference = options.reference;
226+
if (reference !== undefined) {
227+
this.checkReferenceEpoch(reference.name, reference.epoch);
228+
}
222229
const response = await this.connection.queryInterval({
223230
type: 'command',
224231
command: 'query_interval',
225232
interval: interval.toCXXRTL(),
233+
items: reference?.name ?? null,
234+
item_values_encoding: reference ? 'base64(u32)' : null,
235+
diagnostics: options.diagnostics ?? false,
226236
collapse: options.collapse ?? true,
227-
items: reference.name,
228-
item_values_encoding: 'base64(u32)',
229-
diagnostics: false
230237
});
231238
return response.samples.map((cxxrtlSample) => {
232-
const itemValuesBuffer = Buffer.from(cxxrtlSample.item_values!, 'base64');
233-
const itemValuesArray = new Uint32Array(
234-
itemValuesBuffer.buffer,
235-
itemValuesBuffer.byteOffset,
236-
itemValuesBuffer.length / Uint32Array.BYTES_PER_ELEMENT
237-
);
239+
let itemValuesArray = null;
240+
let diagnosticsArray = null;
241+
if (cxxrtlSample.item_values !== undefined) {
242+
const itemValuesBuffer = Buffer.from(cxxrtlSample.item_values, 'base64');
243+
itemValuesArray = new Uint32Array(
244+
itemValuesBuffer.buffer,
245+
itemValuesBuffer.byteOffset,
246+
itemValuesBuffer.length / Uint32Array.BYTES_PER_ELEMENT
247+
);
248+
}
249+
if (cxxrtlSample.diagnostics !== undefined) {
250+
diagnosticsArray = Array.from(cxxrtlSample.diagnostics, Diagnostic.fromCXXRTL);
251+
}
238252
return new Sample(
239253
TimePoint.fromCXXRTL(cxxrtlSample.time),
240-
reference.unbound,
241-
itemValuesArray
254+
reference?.unbound ?? null,
255+
itemValuesArray,
256+
diagnosticsArray,
242257
);
243258
});
244259
}
245260

246-
async queryAtCursor(reference: Reference): Promise<Sample> {
261+
async queryAtCursor(options: {
262+
reference?: Reference,
263+
diagnostics?: boolean
264+
}): Promise<Sample> {
247265
const interval = new TimeInterval(this.timeCursor, this.timeCursor);
248-
const [sample] = await this.queryInterval(reference, interval);
266+
const [sample] = await this.queryInterval(interval, options);
249267
return sample;
250268
}
251269

src/model/sample.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as proto from '../cxxrtl/proto';
2+
import { Location } from './source';
23
import { TimePoint } from './time';
34
import { MemoryVariable, ScalarVariable, Variable } from './variable';
45

@@ -176,16 +177,47 @@ export class Reference {
176177
}
177178
}
178179

180+
export enum DiagnosticType {
181+
Break = 'break',
182+
Print = 'print',
183+
Assert = 'assert',
184+
Assume = 'assume',
185+
}
186+
187+
export class Diagnostic {
188+
constructor(
189+
readonly type: DiagnosticType,
190+
readonly text: string,
191+
readonly location: Location | null,
192+
) {}
193+
194+
static fromCXXRTL(cxxrtlDiagnostic: proto.Diagnostic): Diagnostic {
195+
return new Diagnostic(
196+
<DiagnosticType>cxxrtlDiagnostic.type,
197+
cxxrtlDiagnostic.text,
198+
Location.fromCXXRTL(cxxrtlDiagnostic.src)
199+
);
200+
}
201+
}
202+
179203
export class Sample {
180204
constructor(
181205
readonly time: TimePoint,
182-
readonly reference: UnboundReference,
183-
readonly variableData: Uint32Array,
184-
) {}
206+
readonly reference: UnboundReference | null,
207+
readonly variableData: Uint32Array | null,
208+
readonly diagnostics: Diagnostic[] | null,
209+
) {
210+
if ((this.reference === null) !== (this.variableData === null)) {
211+
throw new Error('A sample must include both a reference and variable data, or neither');
212+
}
213+
}
185214

186215
extract<T>(handle: Handle<T>): T {
187216
if (handle.reference !== this.reference) {
188-
throw new ReferenceError('Handle is not bound to the same reference as the sample');
217+
throw new Error('Handle is not bound to the same reference as the sample');
218+
}
219+
if (this.variableData === null) {
220+
throw new Error('Sample does not include item values');
189221
}
190222
return handle.extractFromRaw(this.variableData);
191223
}

src/ui/hover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class HoverProvider implements vscode.HoverProvider {
2626
}
2727
}
2828
const reference = session.bindReference('hover', unboundReference);
29-
const sample = await session.queryAtCursor(reference);
29+
const sample = await session.queryAtCursor({ reference });
3030
for (const [designation, handle] of reference.allHandles()) {
3131
const variable = designation.variable;
3232
const descriptionText = variableDescription(displayStyle, variable);

0 commit comments

Comments
 (0)