Skip to content

Commit 8fb5394

Browse files
authored
Merge pull request #446 from sugarlabs/gsoc-dmp-2025/week-6/safwan
GSoC/DMP 2025 Week 6: feat(runtime): Update and enhance Symbol Table implementation
2 parents b4e7aec + 4a4f974 commit 8fb5394

File tree

8 files changed

+2214
-605
lines changed

8 files changed

+2214
-605
lines changed

modules/runtime/src/@types/symbol-types.ts

Lines changed: 239 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
/**
44
* Symbol Table Type Definitions
55
*
6-
* This file defines the core types and interfaces for the symbol table system.
7-
* The symbol table acts as a metadata layer above the existing memory module,
8-
* storing information about symbols (variables, functions) rather than their values.
6+
* This file defines the core types and interfaces for the enhanced symbol table system.
7+
* Supports member expressions, enums, arrays, dictionaries, and system variable access control.
98
*/
109

1110
/**
1211
* Types of symbols that can be stored in the symbol table
1312
*/
1413
export enum SymbolType {
15-
/** System-defined variables and functions (built-in) */
14+
/** System-defined variables (immutable by user programs) */
1615
SYSTEM_VARIABLE = 'system_variable',
16+
17+
/** System-defined variables (configurable by main program, immutable by user programs) */
18+
SYSTEM_VARIABLE_CONFIGURABLE = 'system_variable_configurable',
19+
20+
/** System-defined functions (built-in) */
1721
SYSTEM_FUNCTION = 'system_function',
1822

1923
/** User-defined variables */
@@ -56,12 +60,75 @@ export enum DataType {
5660
FUNCTION = 'function',
5761
OBJECT = 'object',
5862
ARRAY = 'array',
63+
DICTIONARY = 'dictionary',
64+
ENUM = 'enum',
65+
PRIMITIVE_VARIABLE = 'primitive_variable',
5966
UNDEFINED = 'undefined',
6067
ANY = 'any',
6168
}
6269

6370
/**
64-
* Additional metadata that can be attached to symbols
71+
* Execution context for access control
72+
*/
73+
export enum ExecutionContext {
74+
/** Main program execution - can modify system configurable variables */
75+
MAIN_PROGRAM = 'main_program',
76+
77+
/** User program execution - cannot modify system variables */
78+
USER_PROGRAM = 'user_program',
79+
}
80+
81+
/**
82+
* Memory pointer to reference memory module locations
83+
*/
84+
export interface MemoryPointer {
85+
readonly threadId: string;
86+
readonly frameId: string;
87+
readonly variableName: string;
88+
}
89+
90+
/**
91+
* Enum-specific metadata
92+
*/
93+
export interface EnumMetadata {
94+
readonly possibleValues: readonly string[];
95+
readonly currentValue?: string;
96+
readonly enumType: string;
97+
}
98+
99+
/**
100+
* Array-specific metadata
101+
*/
102+
export interface ArrayMetadata {
103+
readonly elementType: DataType;
104+
readonly dimensions?: number;
105+
readonly maxLength?: number;
106+
readonly minLength?: number;
107+
}
108+
109+
/**
110+
* Dictionary-specific metadata
111+
*/
112+
export interface DictionaryMetadata {
113+
readonly keyType: DataType;
114+
readonly valueType: DataType;
115+
readonly requiredKeys?: readonly string[];
116+
readonly allowDynamicKeys: boolean;
117+
readonly maxSize?: number;
118+
}
119+
120+
/**
121+
* Object property metadata for member expressions
122+
*/
123+
export interface ObjectPropertyMetadata {
124+
readonly propertyName: string;
125+
readonly propertyType: DataType;
126+
readonly isReadOnly: boolean;
127+
readonly parentObject: string;
128+
}
129+
130+
/**
131+
* Metadata that can be attached to symbols
65132
*/
66133
export interface SymbolMetadata {
67134
/** When the symbol was declared */
@@ -74,6 +141,9 @@ export interface SymbolMetadata {
74141
file?: string;
75142
};
76143

144+
/** Memory pointer to memory module */
145+
readonly memoryPointer?: MemoryPointer;
146+
77147
/** Function-specific metadata */
78148
readonly functionMetadata?: {
79149
parameterCount: number;
@@ -88,6 +158,18 @@ export interface SymbolMetadata {
88158
defaultValue?: unknown;
89159
};
90160

161+
/** Enum-specific metadata */
162+
readonly enumMetadata?: EnumMetadata;
163+
164+
/** Array-specific metadata */
165+
readonly arrayMetadata?: ArrayMetadata;
166+
167+
/** Dictionary-specific metadata */
168+
readonly dictionaryMetadata?: DictionaryMetadata;
169+
170+
/** Object property metadata for member expressions */
171+
readonly objectPropertyMetadata?: ObjectPropertyMetadata;
172+
91173
/** Additional custom metadata */
92174
readonly [key: string]: unknown;
93175
}
@@ -96,9 +178,6 @@ export interface SymbolMetadata {
96178
* Core symbol entry interface
97179
*/
98180
export interface ISymbolEntry {
99-
toPlainObject(): unknown;
100-
isFunction(): any;
101-
getFunctionMetadata(): unknown;
102181
/** Symbol name/identifier */
103182
readonly name: string;
104183

@@ -117,6 +196,9 @@ export interface ISymbolEntry {
117196
/** Whether symbol value can be modified */
118197
readonly isMutable: boolean;
119198

199+
/** Whether symbol can be modified by user programs */
200+
readonly isUserModifiable: boolean;
201+
120202
/** Reference to memory location in the memory module */
121203
readonly memoryLocation?: string;
122204

@@ -128,6 +210,31 @@ export interface ISymbolEntry {
128210

129211
/** Unique identifier for this symbol entry */
130212
readonly id: string;
213+
214+
/** Methods */
215+
withUpdates(updates: {
216+
memoryLocation?: string;
217+
frameId?: string;
218+
metadata?: SymbolMetadata;
219+
}): ISymbolEntry;
220+
221+
canBeShadowed(): boolean;
222+
canBeModified(): boolean;
223+
canBeModifiedByUser(): boolean;
224+
isFunction(): boolean;
225+
isVariable(): boolean;
226+
isEnum(): boolean;
227+
isArray(): boolean;
228+
isDictionary(): boolean;
229+
isMemberReference(): boolean;
230+
getFunctionMetadata(): SymbolMetadata['functionMetadata'] | null;
231+
getVariableMetadata(): SymbolMetadata['variableMetadata'] | null;
232+
getEnumMetadata(): EnumMetadata | null;
233+
getArrayMetadata(): ArrayMetadata | null;
234+
getDictionaryMetadata(): DictionaryMetadata | null;
235+
getObjectPropertyMetadata(): ObjectPropertyMetadata | null;
236+
toPlainObject(): Record<string, unknown>;
237+
toString(): string;
131238
}
132239

133240
/**
@@ -144,6 +251,29 @@ export interface SymbolLookupResult {
144251
readonly isInCurrentScope: boolean;
145252
}
146253

254+
/**
255+
* Member expression resolution result
256+
*/
257+
export interface MemberResolutionResult {
258+
/** Parent object symbol */
259+
readonly parentSymbol: ISymbolEntry;
260+
261+
/** Property name being accessed */
262+
readonly propertyName: string;
263+
264+
/** Property type */
265+
readonly propertyType: DataType;
266+
267+
/** Whether property exists */
268+
readonly exists: boolean;
269+
270+
/** Whether property is readable */
271+
readonly isReadable: boolean;
272+
273+
/** Whether property is writable */
274+
readonly isWritable: boolean;
275+
}
276+
147277
/**
148278
* Symbol table interface
149279
*/
@@ -157,12 +287,16 @@ export interface ISymbolTable<T extends object> {
157287
isMutable?: boolean;
158288
metadata?: SymbolMetadata;
159289
frameId?: string;
290+
executionContext?: ExecutionContext;
160291
},
161292
): ISymbolEntry;
162293

163294
/** Look up a symbol by name */
164295
lookup(name: string): SymbolLookupResult | null;
165296

297+
/** Resolve member expression (a.b) */
298+
resolveMember(objectName: string, propertyName: string): MemberResolutionResult | null;
299+
166300
/** Check if symbol exists in current scope */
167301
existsInCurrentScope(name: string): boolean;
168302

@@ -184,8 +318,20 @@ export interface ISymbolTable<T extends object> {
184318
/** Get current scope depth */
185319
getCurrentScopeDepth(): number;
186320

187-
/** Validate symbol usage */
188-
validateSymbolUsage(name: string, context: string): boolean;
321+
/** Validate symbol usage with access control */
322+
validateSymbolUsage(
323+
name: string,
324+
context: string,
325+
executionContext?: ExecutionContext,
326+
): boolean;
327+
328+
/** Validate member access */
329+
validateMemberAccess(
330+
objectName: string,
331+
propertyName: string,
332+
isWrite: boolean,
333+
executionContext?: ExecutionContext,
334+
): boolean;
189335

190336
/** Remove symbol from current scope */
191337
removeSymbol(name: string): boolean;
@@ -207,50 +353,123 @@ export interface ISymbolResolver<T extends object> {
207353
/** Resolve symbol name to frame ID */
208354
resolveToFrameId(name: string): string | null;
209355

356+
/** Resolve member expression to memory location */
357+
resolveMemberToMemoryLocation(objectName: string, propertyName: string): string | null;
358+
210359
/** Get symbol metadata */
211360
getSymbolMetadata(name: string): SymbolMetadata | null;
212361

213362
/** Check if symbol is accessible from current context */
214-
isSymbolAccessible(name: string): boolean;
363+
isSymbolAccessible(name: string, executionContext?: ExecutionContext): boolean;
364+
365+
/** Check if member is accessible */
366+
isMemberAccessible(
367+
objectName: string,
368+
propertyName: string,
369+
executionContext?: ExecutionContext,
370+
): boolean;
371+
372+
/** Validate enum value */
373+
validateEnumValue(symbolName: string, value: string): boolean;
374+
375+
/** Get enum possible values */
376+
getEnumPossibleValues(symbolName: string): readonly string[] | null;
215377
}
216378

217379
/**
218-
* Errors that can occur in symbol table operations
380+
* Errors for symbol table operations
219381
*/
220382
export class SymbolTableError extends Error {
221383
constructor(
222384
message: string,
223385
public readonly symbolName?: string,
386+
public readonly executionContext?: ExecutionContext,
224387
) {
225388
super(message);
226389
this.name = 'SymbolTableError';
227390
}
228391
}
229392

230393
export class SymbolAlreadyExistsError extends SymbolTableError {
231-
constructor(symbolName: string) {
232-
super(`Symbol "${symbolName}" already exists in current scope`, symbolName);
394+
constructor(symbolName: string, executionContext?: ExecutionContext) {
395+
super(
396+
`Symbol "${symbolName}" already exists in current scope`,
397+
symbolName,
398+
executionContext,
399+
);
233400
this.name = 'SymbolAlreadyExistsError';
234401
}
235402
}
236403

237404
export class SymbolNotFoundError extends SymbolTableError {
238-
constructor(symbolName: string) {
239-
super(`Symbol "${symbolName}" not found`, symbolName);
405+
constructor(symbolName: string, executionContext?: ExecutionContext) {
406+
super(`Symbol "${symbolName}" not found`, symbolName, executionContext);
240407
this.name = 'SymbolNotFoundError';
241408
}
242409
}
243410

244411
export class InvalidSymbolOperationError extends SymbolTableError {
245-
constructor(operation: string, symbolName: string, reason: string) {
246-
super(`Invalid ${operation} operation on symbol "${symbolName}": ${reason}`, symbolName);
412+
constructor(
413+
operation: string,
414+
symbolName: string,
415+
reason: string,
416+
executionContext?: ExecutionContext,
417+
) {
418+
super(
419+
`Invalid ${operation} operation on symbol "${symbolName}": ${reason}`,
420+
symbolName,
421+
executionContext,
422+
);
247423
this.name = 'InvalidSymbolOperationError';
248424
}
249425
}
250426

427+
export class AccessControlError extends SymbolTableError {
428+
constructor(symbolName: string, operation: string, executionContext?: ExecutionContext) {
429+
super(
430+
`Access denied: ${operation} operation on symbol "${symbolName}" not allowed in ${executionContext} context`,
431+
symbolName,
432+
executionContext,
433+
);
434+
this.name = 'AccessControlError';
435+
}
436+
}
437+
438+
export class MemberAccessError extends SymbolTableError {
439+
constructor(
440+
objectName: string,
441+
propertyName: string,
442+
reason: string,
443+
executionContext?: ExecutionContext,
444+
) {
445+
super(
446+
`Member access error: ${objectName}.${propertyName} - ${reason}`,
447+
`${objectName}.${propertyName}`,
448+
executionContext,
449+
);
450+
this.name = 'MemberAccessError';
451+
}
452+
}
453+
454+
export class EnumValidationError extends SymbolTableError {
455+
constructor(
456+
symbolName: string,
457+
value: string,
458+
possibleValues: readonly string[],
459+
executionContext?: ExecutionContext,
460+
) {
461+
super(
462+
`Invalid enum value "${value}" for symbol "${symbolName}". Valid values: ${possibleValues.join(', ')}`,
463+
symbolName,
464+
executionContext,
465+
);
466+
this.name = 'EnumValidationError';
467+
}
468+
}
469+
251470
export class ScopeOperationError extends SymbolTableError {
252-
constructor(operation: string, reason: string) {
253-
super(`Scope ${operation} failed: ${reason}`);
471+
constructor(operation: string, reason: string, executionContext?: ExecutionContext) {
472+
super(`Scope ${operation} failed: ${reason}`, undefined, executionContext);
254473
this.name = 'ScopeOperationError';
255474
}
256475
}

0 commit comments

Comments
 (0)