Skip to content

Commit b4e7aec

Browse files
authored
Merge pull request #445 from sugarlabs/gsoc-dmp-2025/week-4-5/safwan
GSoC/DMP 2025 Week 4-5: feat(runtime): Add Symbol Table
2 parents b5ce407 + 20cbe8e commit b4e7aec

File tree

7 files changed

+1763
-0
lines changed

7 files changed

+1763
-0
lines changed
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
/* eslint-disable @typescript-eslint/no-explicit-any */
3+
/**
4+
* Symbol Table Type Definitions
5+
*
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.
9+
*/
10+
11+
/**
12+
* Types of symbols that can be stored in the symbol table
13+
*/
14+
export enum SymbolType {
15+
/** System-defined variables and functions (built-in) */
16+
SYSTEM_VARIABLE = 'system_variable',
17+
SYSTEM_FUNCTION = 'system_function',
18+
19+
/** User-defined variables */
20+
USER_VARIABLE = 'user_variable',
21+
22+
/** User-defined functions */
23+
USER_FUNCTION = 'user_function',
24+
25+
/** Function parameters */
26+
PARAMETER = 'parameter',
27+
28+
/** Loop iteration variables */
29+
ITERATOR = 'iterator',
30+
}
31+
32+
/**
33+
* Scope levels where symbols can be defined
34+
*/
35+
export enum ScopeType {
36+
/** Global scope - accessible everywhere */
37+
GLOBAL = 'global',
38+
39+
/** Function scope - accessible within function */
40+
FUNCTION = 'function',
41+
42+
/** Block scope - accessible within block */
43+
BLOCK = 'block',
44+
45+
/** Parameter scope - function parameters */
46+
PARAMETER = 'parameter',
47+
}
48+
49+
/**
50+
* Data types for symbol values
51+
*/
52+
export enum DataType {
53+
NUMBER = 'number',
54+
STRING = 'string',
55+
BOOLEAN = 'boolean',
56+
FUNCTION = 'function',
57+
OBJECT = 'object',
58+
ARRAY = 'array',
59+
UNDEFINED = 'undefined',
60+
ANY = 'any',
61+
}
62+
63+
/**
64+
* Additional metadata that can be attached to symbols
65+
*/
66+
export interface SymbolMetadata {
67+
/** When the symbol was declared */
68+
readonly declaredAt?: string;
69+
70+
/** Source location information */
71+
readonly sourceLocation?: {
72+
line: number;
73+
column: number;
74+
file?: string;
75+
};
76+
77+
/** Function-specific metadata */
78+
readonly functionMetadata?: {
79+
parameterCount: number;
80+
parameterNames: readonly string[];
81+
returnType?: DataType;
82+
isAsync?: boolean;
83+
};
84+
85+
/** Variable-specific metadata */
86+
readonly variableMetadata?: {
87+
isInitialized: boolean;
88+
defaultValue?: unknown;
89+
};
90+
91+
/** Additional custom metadata */
92+
readonly [key: string]: unknown;
93+
}
94+
95+
/**
96+
* Core symbol entry interface
97+
*/
98+
export interface ISymbolEntry {
99+
toPlainObject(): unknown;
100+
isFunction(): any;
101+
getFunctionMetadata(): unknown;
102+
/** Symbol name/identifier */
103+
readonly name: string;
104+
105+
/** Type of symbol */
106+
readonly symbolType: SymbolType;
107+
108+
/** Scope where symbol is defined */
109+
readonly scopeType: ScopeType;
110+
111+
/** Data type of symbol value */
112+
readonly dataType: DataType;
113+
114+
/** Whether symbol is user-defined or system-defined */
115+
readonly isUserDefined: boolean;
116+
117+
/** Whether symbol value can be modified */
118+
readonly isMutable: boolean;
119+
120+
/** Reference to memory location in the memory module */
121+
readonly memoryLocation?: string;
122+
123+
/** Frame ID in the LayeredMap where symbol is stored */
124+
readonly frameId?: string;
125+
126+
/** Additional metadata */
127+
readonly metadata?: SymbolMetadata;
128+
129+
/** Unique identifier for this symbol entry */
130+
readonly id: string;
131+
}
132+
133+
/**
134+
* Symbol lookup result
135+
*/
136+
export interface SymbolLookupResult {
137+
/** Found symbol entry */
138+
readonly entry: ISymbolEntry;
139+
140+
/** Scope depth where symbol was found (0 = current scope) */
141+
readonly scopeDepth: number;
142+
143+
/** Whether symbol was found in current scope or inherited */
144+
readonly isInCurrentScope: boolean;
145+
}
146+
147+
/**
148+
* Symbol table interface
149+
*/
150+
export interface ISymbolTable<T extends object> {
151+
/** Declare a new symbol */
152+
declare(
153+
name: string,
154+
symbolType: SymbolType,
155+
dataType: DataType,
156+
options?: {
157+
isMutable?: boolean;
158+
metadata?: SymbolMetadata;
159+
frameId?: string;
160+
},
161+
): ISymbolEntry;
162+
163+
/** Look up a symbol by name */
164+
lookup(name: string): SymbolLookupResult | null;
165+
166+
/** Check if symbol exists in current scope */
167+
existsInCurrentScope(name: string): boolean;
168+
169+
/** Check if symbol exists in any accessible scope */
170+
existsInAnyScope(name: string): boolean;
171+
172+
/** Get all symbols in current scope */
173+
getCurrentScopeSymbols(): readonly ISymbolEntry[];
174+
175+
/** Get all symbols in all accessible scopes */
176+
getAllAccessibleSymbols(): readonly ISymbolEntry[];
177+
178+
/** Enter a new scope */
179+
pushScope(): void;
180+
181+
/** Exit current scope */
182+
popScope(): void;
183+
184+
/** Get current scope depth */
185+
getCurrentScopeDepth(): number;
186+
187+
/** Validate symbol usage */
188+
validateSymbolUsage(name: string, context: string): boolean;
189+
190+
/** Remove symbol from current scope */
191+
removeSymbol(name: string): boolean;
192+
193+
/** Clear all symbols in current scope */
194+
clearCurrentScope(): void;
195+
196+
/** Reset symbol table to initial state */
197+
reset(): void;
198+
}
199+
200+
/**
201+
* Symbol resolver interface for name resolution
202+
*/
203+
export interface ISymbolResolver<T extends object> {
204+
/** Resolve symbol name to memory location */
205+
resolveToMemoryLocation(name: string): string | null;
206+
207+
/** Resolve symbol name to frame ID */
208+
resolveToFrameId(name: string): string | null;
209+
210+
/** Get symbol metadata */
211+
getSymbolMetadata(name: string): SymbolMetadata | null;
212+
213+
/** Check if symbol is accessible from current context */
214+
isSymbolAccessible(name: string): boolean;
215+
}
216+
217+
/**
218+
* Errors that can occur in symbol table operations
219+
*/
220+
export class SymbolTableError extends Error {
221+
constructor(
222+
message: string,
223+
public readonly symbolName?: string,
224+
) {
225+
super(message);
226+
this.name = 'SymbolTableError';
227+
}
228+
}
229+
230+
export class SymbolAlreadyExistsError extends SymbolTableError {
231+
constructor(symbolName: string) {
232+
super(`Symbol "${symbolName}" already exists in current scope`, symbolName);
233+
this.name = 'SymbolAlreadyExistsError';
234+
}
235+
}
236+
237+
export class SymbolNotFoundError extends SymbolTableError {
238+
constructor(symbolName: string) {
239+
super(`Symbol "${symbolName}" not found`, symbolName);
240+
this.name = 'SymbolNotFoundError';
241+
}
242+
}
243+
244+
export class InvalidSymbolOperationError extends SymbolTableError {
245+
constructor(operation: string, symbolName: string, reason: string) {
246+
super(`Invalid ${operation} operation on symbol "${symbolName}": ${reason}`, symbolName);
247+
this.name = 'InvalidSymbolOperationError';
248+
}
249+
}
250+
251+
export class ScopeOperationError extends SymbolTableError {
252+
constructor(operation: string, reason: string) {
253+
super(`Scope ${operation} failed: ${reason}`);
254+
this.name = 'ScopeOperationError';
255+
}
256+
}

0 commit comments

Comments
 (0)