Skip to content

Commit 9d6b299

Browse files
refactored parser, made it C strict (#797)
* refactored parser, made it C strict * fixed hex parsing * added more const folding, added perf stats * Parser: Now can read types from ScvdModel * fixed parser fetch of scalar types * changed _addr to return base if just one entry (for read) * removed pre-evaluation and forwarding of types from typedef * updated shown item behavior to match UV4 * aligned "// generated with AI", disabled perf stats * removed parser global API and fixed ScvdExpression accordingly. * fixed: gathering of execution context for parsing * extended unit tests, fixed MAC address printing and "1 off" mask. Added integration tests for them
1 parent 5c1a214 commit 9d6b299

130 files changed

Lines changed: 5349 additions & 1226 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/views/component-viewer/component-viewer-instance.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { StatementEngine } from './statement-engine/statement-engine';
2525
import { ScvdEvalContext } from './scvd-eval-context';
2626
import { GDBTargetDebugSession, GDBTargetDebugTracker } from '../../debug-session';
2727
import { ScvdGuiTree } from './scvd-gui-tree';
28-
import { perf } from './stats-config';
2928

3029

3130
const xmlOpts: ParserOptions = {
@@ -178,7 +177,6 @@ export class ComponentViewerInstance {
178177
await this.executeStatements(this._guiTree);
179178
stats.push(this.getStats('end'));
180179
console.log('ComponentViewerInstance update stats:\n' + stats.join('\n '));
181-
perf?.logSummaries();
182180
}
183181

184182
private async readFileToBuffer(filePath: URI): Promise<Buffer> {

src/views/component-viewer/component-viewer-main.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { URI } from 'vscode-uri';
2121
import { ComponentViewerTreeDataProvider } from './component-viewer-tree-view';
2222
import { logger } from '../../logger';
2323
import type { ScvdGuiInterface } from './model/scvd-gui-interface';
24+
import { perf, parsePerf } from './stats-config';
2425

2526
export type fifoUpdateReason = 'sessionChanged' | 'refreshTimer' | 'stackTrace' | 'stackItemChanged';
2627

@@ -108,6 +109,7 @@ export class ComponentViewer {
108109
if (scvdFilesPaths.length === 0) {
109110
return undefined;
110111
}
112+
parsePerf?.reset();
111113
const cbuildRunInstances: ComponentViewerInstance[] = [];
112114
for (const scvdFilePath of scvdFilesPaths) {
113115
const instance = new ComponentViewerInstance();
@@ -116,6 +118,7 @@ export class ComponentViewer {
116118
cbuildRunInstances.push(instance);
117119
}
118120
}
121+
parsePerf?.logSummary();
119122
// Store loaded instances, set default lock state to false
120123
this._instances.push(...cbuildRunInstances.map(instance => ({
121124
componentViewerInstance: instance,
@@ -268,6 +271,8 @@ export class ComponentViewer {
268271
if (this._instances.length === 0) {
269272
return;
270273
}
274+
perf?.resetBackendStats();
275+
perf?.resetUiStats();
271276
const roots: ScvdGuiInterface[] = [];
272277
for (const instance of this._instances) {
273278
// Check if instance belongs to the active session, if not skip it and clear its data from the tree view.
@@ -291,7 +296,7 @@ export class ComponentViewer {
291296
roots[roots.length - 1].isRootInstance = true;
292297
}
293298
}
299+
perf?.logSummaries();
294300
this._componentViewerTreeDataProvider?.setRoots(roots);
295301
}
296302
}
297-

src/views/component-viewer/data-host/memory-host.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ export class MemoryHost {
420420
console.error(`getElementTargetBase: unknown symbol "${name}"`);
421421
return undefined;
422422
}
423+
if (m.bases.length === 1) {
424+
return m.bases[0];
425+
}
423426
if (index < 0 || index >= m.bases.length) {
424427
console.error(`getElementTargetBase: index ${index} out of range for "${name}"`);
425428
return undefined;

src/views/component-viewer/model/scvd-expression.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@
1717
// https://arm-software.github.io/CMSIS-View/main/scvd_expression.html
1818

1919

20-
import { parseExpression, ParseResult } from '../parser-evaluator/parser';
20+
import { ParseResult } from '../parser-evaluator/parser';
2121
import { EvaluateResult } from '../parser-evaluator/evaluator';
2222
import { ScvdNode } from './scvd-node';
23-
import { ExecutionContext } from '../scvd-eval-context';
2423

2524
export class ScvdExpression extends ScvdNode {
2625
private _expression: string | undefined;
2726
private _scvdVarName: string | undefined;
2827
private _expressionAst: ParseResult | undefined;
2928
private _isPrintExpression: boolean = false;
30-
private _executionContext: ExecutionContext | undefined;
3129

3230
constructor(
3331
parent: ScvdNode | undefined,
@@ -66,11 +64,15 @@ export class ScvdExpression extends ScvdNode {
6664
}
6765

6866
private async evaluateExpression(): Promise<EvaluateResult> {
69-
if (this.expressionAst === undefined || this._executionContext === undefined) {
67+
const executionContext = this.getExecutionContext();
68+
if (this.expressionAst === undefined || executionContext === undefined) {
7069
console.error(this.getLineInfoStr(), 'Expression evaluation missing AST or execution context');
7170
return undefined;
7271
}
73-
return this._executionContext.evaluator.evaluateParseResult(this.expressionAst, this._executionContext.evalContext);
72+
if (executionContext && this._executionContext !== executionContext) {
73+
this._executionContext = executionContext;
74+
}
75+
return executionContext.evaluator.evaluateParseResult(this.expressionAst, executionContext.evalContext);
7476
}
7577

7678
public override getValue(): Promise<EvaluateResult> {
@@ -108,7 +110,16 @@ export class ScvdExpression extends ScvdNode {
108110
}
109111

110112
if (this.expressionAst === undefined) { // if already parsed by dependency, skip parsing
111-
const expressionAst = parseExpression(expression, this.isPrintExpression);
113+
const executionContext = this.getExecutionContext();
114+
if (executionContext && this._executionContext !== executionContext) {
115+
this._executionContext = executionContext;
116+
}
117+
const parser = executionContext?.parser;
118+
if (!parser) {
119+
console.error(this.getLineInfoStr(), 'Expression parsing missing execution context or parser');
120+
return false;
121+
}
122+
const expressionAst = parser.parseExpression(expression, this.isPrintExpression);
112123
if (expressionAst !== undefined && expressionAst.diagnostics.length === 0) {
113124
this.expressionAst = expressionAst;
114125
}
@@ -122,10 +133,6 @@ export class ScvdExpression extends ScvdNode {
122133
return super.configure();
123134
}
124135

125-
public override setExecutionContext(_executionContext: ExecutionContext) {
126-
this._executionContext = _executionContext;
127-
}
128-
129136
public override validate(prevResult: boolean): boolean {
130137
const expression = this.expression;
131138
if (expression === undefined) {

src/views/component-viewer/model/scvd-format-specifier.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class ScvdFormatSpecifier {
108108

109109
if (kind === 'uint') {
110110
if (bits && bits < 32) {
111-
const mask = (1 << bits) >>> 0;
111+
const mask = ((1 << bits) - 1) >>> 0;
112112
return (((value as number) >>> 0) & mask).toString(10);
113113
}
114114
return ((value as number) >>> 0).toString(10);
@@ -221,9 +221,12 @@ export class ScvdFormatSpecifier {
221221
}
222222
case 'M': {
223223
if (value instanceof Uint8Array) {
224-
return this.formatMac(value);
224+
return this.format_M(value);
225225
}
226-
return this.format_M(value as number | string);
226+
if (typeof value === 'string') {
227+
return this.format_M(value);
228+
}
229+
return String(value);
227230
}
228231
case 'T': {
229232
return this.format_T(value, typeInfo, padHex);
@@ -389,20 +392,12 @@ export class ScvdFormatSpecifier {
389392
}
390393

391394

392-
public format_M(value: number | string): string {
395+
public format_M(value: Uint8Array | string): string {
393396
if (typeof value === 'string') {
394397
const cleaned = value.replace(/[^0-9a-fA-F]/g, '').slice(0, 12).padStart(12, '0');
395398
return cleaned.match(/.{1,2}/g)?.join('-').toUpperCase() ?? value;
396399
}
397-
const n = Number(value);
398-
if (!Number.isFinite(n)) {
399-
return `${value}`;
400-
}
401-
const parts: string[] = [];
402-
for (let i = 5; i >= 0; i--) {
403-
parts.push(((n >> (i * 8)) & 0xFF).toString(16).padStart(2, '0'));
404-
}
405-
return parts.join('-').toUpperCase();
400+
return this.formatMac(value);
406401
}
407402

408403
public format_T(value: unknown, typeInfo?: FormatTypeInfo, padZeroes: boolean = false): string {

src/views/component-viewer/model/scvd-node.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ScvdNodeSymbolCache } from './scvd-node-cache';
2626
*/
2727
export abstract class ScvdNode extends ScvdBase {
2828
private _symbolsCache = new ScvdNodeSymbolCache();
29+
protected _executionContext: ExecutionContext | undefined;
2930

3031
public override get parent(): ScvdNode | undefined {
3132
return super.parent as ScvdNode | undefined;
@@ -90,6 +91,14 @@ export abstract class ScvdNode extends ScvdBase {
9091
}
9192

9293
public setExecutionContext(_executionContext: ExecutionContext) {
94+
this._executionContext = _executionContext;
95+
}
96+
97+
public getExecutionContext(): ExecutionContext | undefined {
98+
if (this._executionContext !== undefined) {
99+
return this._executionContext;
100+
}
101+
return this.parent?.getExecutionContext();
93102
}
94103

95104
// default condition always true

src/views/component-viewer/model/scvd-read.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ export class ScvdRead extends ScvdNode {
193193
return this.type?.getMember(property);
194194
}
195195

196+
public override getElementRef(): ScvdNode | undefined {
197+
return this.type ?? undefined;
198+
}
199+
196200
public override getValueType(): string | undefined {
197201
return this.type?.getValueType();
198202
}

src/views/component-viewer/model/scvd-symbol.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616

1717
// https://arm-software.github.io/CMSIS-View/main/elem_component_viewer.html
1818

19-
import { ExecutionContext } from '../scvd-eval-context';
2019
import { ScvdNode } from './scvd-node';
2120
import { MemberInfo } from '../scvd-debug-target';
2221

2322
export class ScvdSymbol extends ScvdNode {
2423
private _symbol: string | undefined;
25-
private _executionContext: ExecutionContext | undefined;
2624
private _address: number | undefined;
2725
private _memberInfo: MemberInfo[] = [];
2826

@@ -84,9 +82,4 @@ export class ScvdSymbol extends ScvdNode {
8482
return memberInfo?.offset;
8583
}
8684

87-
public override setExecutionContext(executionContext: ExecutionContext) {
88-
this._executionContext = executionContext;
89-
}
90-
91-
9285
}

src/views/component-viewer/model/scvd-typedef.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,17 @@ export class ScvdTypedef extends ScvdNode {
241241
}
242242

243243
public async calculateTypedef() {
244+
// Ensure typedef expressions are parsed before any value access.
245+
this._size?.configure();
246+
for (const member of this._member) {
247+
member.offset?.configure();
248+
member.size?.configure();
249+
}
250+
for (const varItem of this._var) {
251+
varItem.size?.configure();
252+
varItem.offset?.configure();
253+
}
254+
244255
if (this.import !== undefined) {
245256
await this.import.fetchSymbolInformation();
246257
}

0 commit comments

Comments
 (0)